-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
130: Invalidate inline caches on method mutation r=ptersilie a=ltratt This fixes the problem identified in SOM-st/SOM#35 and which, AFAIK, affects all SOM implementations: mutating a method in a class causes incorrect behaviour if an inline cache exists for that call (e.g. yksom (before this PR) and Java SOM could "ignore" the change if a cache had been created; and C SOM apparently crashes!). This PR fixes the problem for yksom. It does so in a brute force way: when a method in any class is changed, every inline cache in the VM is reset. This makes correctness easy to reason about, though clearly it is less efficient than more nuanced approaches. The way we do this is sort-of interesting from a Rust perspective. There are two obvious ways to model this: * Have every SOM `Array` have a `bool` that says "if I'm mutated, flush all inline caches". * Subclass the `Array` struct (in Rust) so that only instances of the `MethodArray` subclass flush inline caches on mutation. The former is ugly, the latter seems impossible: Rust doesn't have subclasses, and traits only partially model them. In this case, the `bool` would probably be most efficient, but it's just really ugly. So I tried to make the latter case work, even though it doesn't appear to be possible. In particular, and perhaps surprisingly (though there are good reasons for this), a trait object `T1 + T2` cannot be coerced into a trait object of either `T1` or `T2`. This PR uses a simple way to solve this problem: 1. We define a trait `Array` 2. We define two structs `NormalArray` (which is the old `Array` struct renamed) and `MethodsArray` (which is only used for the arrays of methods in `Class`es). 3. We add a `to_array` function to `Obj` which returns (simplified) `&dyn Array`. Given a `&dyn Obj` we can then turn it into a `&dyn Array` by calling `to_array` *if and only if* an implementation of `to_array` is provided. Only `NormalArray` and `MethodsArray` implement this. Using this, we can get from a `Val` to a `&dyn Array` by calling (simplified) `val.tobj().to_array()`. Yes, it means we have two dynamically dispatched function calls, but it means that we have a relatively nice way of separating out the behaviour of normal arrays from method arrays. Most of the PR is thus shuffling code around (and duplicating some code): the real meat is in 0889b12. Co-authored-by: Laurence Tratt <[email protected]>
- Loading branch information
Showing
9 changed files
with
200 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
" | ||
VM: | ||
stdout: | ||
#b | ||
#c | ||
" | ||
|
||
mutate_methods = ( | ||
run = ( | ||
| g_idx h_idx ms | | ||
self f println. | ||
ms := mutate_methods methods. | ||
ms doIndexes: [:i | | ||
(((ms at: i) signature) == #g) ifTrue: [ g_idx := i ]. | ||
(((ms at: i) signature) == #h) ifTrue: [ h_idx := i ]. | ||
]. | ||
mutate_methods methods at: g_idx put: (ms at: h_idx). | ||
self f println. | ||
) | ||
|
||
f = ( ^self g ) | ||
g = ( ^#b. ) | ||
h = ( ^#c. ) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
" | ||
VM: | ||
status: success | ||
stdout: | ||
#b | ||
#c | ||
" | ||
|
||
test = test_super ( | ||
run = ( | ||
| g_idx h_idx ms | | ||
self f println. | ||
ms := test_super methods. | ||
ms doIndexes: [:i | | ||
(((ms at: i) signature) == #g) ifTrue: [ g_idx := i ]. | ||
(((ms at: i) signature) == #h) ifTrue: [ h_idx := i ]. | ||
]. | ||
test_super methods at: g_idx put: (ms at: h_idx). | ||
self f println. | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
test_super = ( | ||
f = ( ^self g ) | ||
g = ( ^#b. ) | ||
h = ( ^#c. ) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.