9 Commits

Author SHA1 Message Date
John Alanbrook
828a1ddcf7 merge trampoline and call_ic 2025-12-31 16:58:39 -06:00
John Alanbrook
8abee37622 persistent current frame 2025-12-31 14:28:43 -06:00
John Alanbrook
7c3cce1ce2 works 2025-12-31 12:45:32 -06:00
John Alanbrook
334f3a789b runs 2025-12-31 11:09:18 -06:00
John Alanbrook
e21cd4e70b tail call 2025-12-31 09:19:39 -06:00
John Alanbrook
41eb4bf6f7 bench 2025-12-30 22:56:31 -06:00
John Alanbrook
5f761cc7af wire callinternal to use trampoline 2025-12-30 16:58:06 -06:00
John Alanbrook
7ae5a0c06b null + anything = null 2025-12-30 14:40:54 -06:00
John Alanbrook
0664c11af6 set up quickening for adds 2025-12-30 00:39:43 -06:00
6 changed files with 1797 additions and 294 deletions

View File

@@ -808,7 +808,6 @@ if (!locator)
stone(globalThis)
var rads = use_core("math/radians")
log.console(rads)
$_.clock(_ => {
// Get capabilities for the main program

View File

@@ -74,7 +74,7 @@ foreach file: scripts
endforeach
srceng = 'source'
includes = [srceng, 'internal', 'debug', 'net', 'archive', 'math']
includes = [srceng, 'internal', 'debug', 'net', 'archive']
foreach file : src
full_path = join_paths(srceng, file)

View File

@@ -28,6 +28,10 @@
#include <stddef.h>
#endif
#ifndef NDEBUG
#include <assert.h>
#endif
struct list_head {
struct list_head *prev;
struct list_head *next;
@@ -82,6 +86,29 @@ static inline int list_empty(struct list_head *el)
return el->next == el;
}
/* Move all elements from 'src' to 'dst', leaving 'src' empty.
'dst' must be empty before this call. */
static inline void list_splice(struct list_head *dst, struct list_head *src)
{
#ifndef NDEBUG
assert(dst != src);
assert(list_empty(dst));
#endif
if (!list_empty(src)) {
struct list_head *first = src->next;
struct list_head *last = src->prev;
/* Link dst to src's elements */
dst->next = first;
dst->prev = last;
first->prev = dst;
last->next = dst;
/* Reinitialize src as empty */
init_list_head(src);
}
}
#define list_for_each(el, head) \
for(el = (head)->next; el != (head); el = el->next)

View File

@@ -329,6 +329,39 @@ DEF( call3, 1, 1, 1, npopx)
DEF( is_null, 1, 1, 1, none)
DEF( typeof_is_function, 1, 1, 1, none)
/* Per-site IC opcodes with quickening support
* These opcodes embed an IC index instead of an atom. The atom is stored
* in the IC slot itself. This allows direct IC lookup without hashing.
*
* Quickening: get_field (atom) -> get_field_ic (ic_index)
* put_field (atom) -> put_field_ic (ic_index)
*
* The ic_index is a u16 that indexes into the function's per_site_ic array.
* Format: opcode (1 byte) + ic_index (2 bytes) = 3 bytes total
*/
DEF( get_field_ic, 3, 1, 1, u16) /* quickened from get_field, ic_index operand */
DEF( get_field2_ic, 3, 1, 2, u16) /* quickened from get_field2, ic_index operand */
DEF( put_field_ic, 3, 2, 0, u16) /* quickened from put_field, ic_index operand */
/* Fused opcodes for get_loc + get_field pattern
* These eliminate a dup/free pair by reading the local without pushing it,
* then doing the field lookup directly.
*
* Format: opcode (1 byte) + loc_idx (2 bytes) + ic_index (2 bytes) = 5 bytes
* Stack: -> value (reads local, does field lookup, pushes result)
*
* The local is NOT consumed (no refcount change to the local variable).
*/
DEF(get_field_loc_ic, 5, 0, 1, u32) /* fused: get_loc(idx) + get_field_ic, operand is loc_idx:u16 + ic_idx:u16 */
DEF(get_field_arg_ic, 5, 0, 1, u32) /* fused: get_arg(idx) + get_field_ic, operand is arg_idx:u16 + ic_idx:u16 */
/* Fused opcodes for put_field pattern with local source
* Format: opcode (1 byte) + loc_idx (2 bytes) + ic_index (2 bytes) = 5 bytes
* Stack: value -> (reads local as object, sets field to value from stack)
*/
DEF(put_field_loc_ic, 5, 1, 0, u32) /* fused: get_loc(idx) + swap + put_field_ic, operand is loc_idx:u16 + ic_idx:u16 */
DEF(put_field_arg_ic, 5, 1, 0, u32) /* fused: get_arg(idx) + swap + put_field_ic, operand is arg_idx:u16 + ic_idx:u16 */
#endif
#undef DEF

File diff suppressed because it is too large Load Diff

View File

@@ -145,26 +145,6 @@ return {
if (!caught) throw "string + boolean should throw"
},
test_null_plus_string_throws: function() {
var caught = false
try {
var x = null + "hello"
} catch (e) {
caught = true
}
if (!caught) throw "null + string should throw"
},
test_string_plus_null_throws: function() {
var caught = false
try {
var x = "hello" + null
} catch (e) {
caught = true
}
if (!caught) throw "string + null should throw"
},
// ============================================================================
// COMPARISON OPERATORS
// ============================================================================