summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>2021-01-22 14:57:44 -0500
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:27 -0400
commit738160db0a7fb32d609133fb68fbdff02ff315f2 (patch)
tree93011f83550ddd21559cf1b9c7fc4c8ed2cb2105
parent7efde1bfb486aa7bb57f5f355a13be040a6973ff (diff)
Write ctx_diff() function to compate ctx_t objects
-rw-r--r--ujit_core.c48
-rw-r--r--ujit_core.h1
2 files changed, 44 insertions, 5 deletions
diff --git a/ujit_core.c b/ujit_core.c
index 2143ab3923..8e7ce31330 100644
--- a/ujit_core.c
+++ b/ujit_core.c
@@ -103,6 +103,42 @@ ctx_get_top_type(ctx_t* ctx)
return ctx->temp_types[ctx->stack_size - 1];
}
+/**
+Compute a difference score for two context objects
+Returns 0 if the two contexts are the same
+Returns -1 if incompatible
+Returns > 0 if different but compatible
+*/
+int ctx_diff(const ctx_t* src, const ctx_t* dst)
+{
+ if (dst->stack_size != src->stack_size)
+ return -1;
+
+ if (dst->self_is_object != src->self_is_object)
+ return -1;
+
+ // Difference sum
+ int diff = 0;
+
+ // For each temporary variable
+ for (size_t i = 0; i < MAX_TEMP_TYPES; ++i)
+ {
+ int t_src = src->temp_types[i];
+ int t_dst = dst->temp_types[i];
+
+ if (t_dst != t_src)
+ {
+ // It's OK to lose some type information
+ if (t_dst == T_NONE)
+ diff += 1;
+ else
+ return -1;
+ }
+ }
+
+ return diff;
+}
+
// Add an incoming branch for a given block version
static void add_incoming(block_t* p_block, uint32_t branch_idx)
{
@@ -118,16 +154,18 @@ static void add_incoming(block_t* p_block, uint32_t branch_idx)
block_t* find_block_version(blockid_t blockid, const ctx_t* ctx)
{
// If there exists a version for this block id
- st_data_t st_version;
- if (rb_st_lookup(version_tbl, (st_data_t)&blockid, &st_version)) {
- return (block_t*)st_version;
- }
+ block_t* first_version;
+ if (!rb_st_lookup(version_tbl, (st_data_t)&blockid, (st_data_t*)&first_version))
+ return NULL;
//
// TODO: use the ctx parameter to search existing versions for a match
//
- return NULL;
+ // Check that the version found is actually compatible
+ RUBY_ASSERT(ctx_diff(ctx, &first_version->ctx) >= 0);
+
+ return first_version;
}
// Compile a new block version immediately
block_t* gen_block_version(blockid_t blockid, const ctx_t* start_ctx)
diff --git a/ujit_core.h b/ujit_core.h
index ff73890e4d..7b230d779d 100644
--- a/ujit_core.h
+++ b/ujit_core.h
@@ -130,6 +130,7 @@ x86opnd_t ctx_stack_push(ctx_t* ctx, int type);
x86opnd_t ctx_stack_pop(ctx_t* ctx, size_t n);
x86opnd_t ctx_stack_opnd(ctx_t* ctx, int32_t idx);
int ctx_get_top_type(ctx_t* ctx);
+int ctx_diff(const ctx_t* src, const ctx_t* dst);
block_t* find_block_version(blockid_t blockid, const ctx_t* ctx);
block_t* gen_block_version(blockid_t blockid, const ctx_t* ctx);