Commit de3e7661 authored by Camil Staps's avatar Camil Staps 🐧

Port RtoAC to WebAssembly (for performance; see #82)

parent 2f4f06d0
Pipeline #35840 passed with stages
in 10 minutes and 54 seconds
This diff is collapsed.
......@@ -618,21 +618,7 @@ class ABCInterpreter {
expR: Math.exp,
lnR: Math.log,
log10R: Math.log10,
RtoAC_words_needed: function(v) {
v=Number(0+v).toPrecision(15).replace(/\.?0*$/,'');
return 2+((v.length+7)>>3);
},
RtoAC: function (dest, v) {
v=Number(0+v).toPrecision(15).replace(/\.?0*$/,'');
me.memory_array[dest/4]=5*8+2; // __STRING__
me.memory_array[dest/4+1]=0;
me.memory_array[dest/4+2]=v.length;
me.memory_array[dest/4+3]=0;
const arr=new Uint8Array(me.memory_array.buffer, dest+16);
for (var i=0; i<v.length; i++)
arr[i]=v.charCodeAt(i);
return dest+16+(((v.length+7)>>3)<<3);
},
RtoAC: util.instance.exports.convert_real_to_string,
}
};
Object.assign(interpreter_imports.clean, opts.interpreter_imports);
......
......@@ -21,7 +21,7 @@ enum section_type {
#define _4chars2int(a,b,c,d) ((uint64_t) (a+(b<<8)+(c<<16)+(d<<24)))
#define _7chars2int(a,b,c,d,e,f,g) ((uint64_t) (a+(b<<8)+(c<<16)+(d<<24)+((uint64_t)e<<32)+((uint64_t)f<<40)+((uint64_t)g<<48)))
#define _8chars2int(a,b,c,d,e,f,g,h) ((uint64_t) (a+(b<<8)+(c<<16)+(d<<24)+((uint64_t)e<<32)+((uint64_t)f<<40)+((uint64_t)g<<48)+((uint64_t)h<<56)))
uint64_t prelinker_preamble[669] = {
uint64_t prelinker_preamble[690] = {
/* 0 */ 0, 0, 0, 7, _7chars2int('_','A','R','R','A','Y','_'),
/* 5 */ 0, 0, 0, 8, _8chars2int('_','S','T','R','I','N','G','_'),
/* 10 */ 0, 0, 0, 4, _4chars2int('B','O','O','L'),
......@@ -68,19 +68,50 @@ uint64_t prelinker_preamble[669] = {
10*8+2,0, 10*8+2,1,
/* 664 */
258, 2, _2chars2int('i','i'), 4, _4chars2int('F','I','L','E'),
/* 669 */
/* 669 power10_table (for RtoAC) */
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
/* 685 power10_table2 (for RtoAC) */
0,0,0,0,0,
/* 690 */
};
void prepare_preamble(void) {
/* small integers */
for (int i=0; i<=32; i++) {
prelinker_preamble[30+i*2]=25*8+2; /* INT+2 */
prelinker_preamble[30+i*2+1]=i;
}
/* static characters */
for (int i=0; i<256; i++) {
prelinker_preamble[146+i*2]=15*8+2; /* CHAR+2 */
prelinker_preamble[146+i*2+1]=i;
}
/* power10_table */
*(double*)&prelinker_preamble[669]=1.0e00;
*(double*)&prelinker_preamble[670]=1.0e01;
*(double*)&prelinker_preamble[671]=1.0e02;
*(double*)&prelinker_preamble[672]=1.0e03;
*(double*)&prelinker_preamble[673]=1.0e04;
*(double*)&prelinker_preamble[674]=1.0e05;
*(double*)&prelinker_preamble[675]=1.0e06;
*(double*)&prelinker_preamble[676]=1.0e07;
*(double*)&prelinker_preamble[677]=1.0e08;
*(double*)&prelinker_preamble[678]=1.0e09;
*(double*)&prelinker_preamble[679]=1.0e10;
*(double*)&prelinker_preamble[680]=1.0e11;
*(double*)&prelinker_preamble[681]=1.0e12;
*(double*)&prelinker_preamble[682]=1.0e13;
*(double*)&prelinker_preamble[683]=1.0e14;
*(double*)&prelinker_preamble[684]=1.0e15;
/* power10_table2 */
*(double*)&prelinker_preamble[685]=1.0e16;
*(double*)&prelinker_preamble[686]=1.0e32;
*(double*)&prelinker_preamble[687]=1.0e64;
*(double*)&prelinker_preamble[688]=1.0e128;
*(double*)&prelinker_preamble[689]=1.0e256;
}
void write_section(FILE *f, enum section_type type, uint32_t len, uint64_t *data) {
......
#pragma once
extern uint64_t prelinker_preamble[669];
extern uint64_t prelinker_preamble[690];
......@@ -17,11 +17,17 @@ instr_mulUUL t = instr_unimplemented t // TODO
instr_RtoAC :: !Target -> Target
instr_RtoAC t = (
ensure_hp 5 :. // upper bound; sometimes as little as 3 words are needed
new_local TReal (to_real (B @ 0)) \r ->
new_local TPtrOffset (ex_to_expr (Ecall "clean_RtoAC_words_needed" [expr_to_ex r])) \lw ->
ensure_hp lw :.
A @ 1 .= to_word Hp :.
Hp .= (ex_to_expr (Ecall "clean_RtoAC" [expr_to_ex Hp,expr_to_ex r]) ::: TPtr TWord) :.
Hp @ 0 .= STRING__ptr + lit_word 2 :.
new_local TWord (to_word Hp) \old_hp ->
advance_ptr Hp 2 :.
new_local TWord (to_word (ex_to_expr (Ecall "clean_RtoAC" [expr_to_ex r,expr_to_ex Hp]) ::: TPtrOffset)) \new_hp ->
Hp @ -1 .= new_hp - to_word Hp :.
Hp .= to_word_ptr ((new_hp + lit_word 7) &. lit_word -8) :.
// correct hp-free counter because we use an upper bound above
Hp_free += lit_hword 5 - to_ptr_offset ((to_word Hp - old_hp) >>. lit_word 3) :.
advance_ptr Pc 1 :.
advance_ptr A 1 :.
advance_ptr B 1
......
......@@ -166,8 +166,7 @@ where
, "(func $clean_expR (import \"clean\" \"expR\") (param f64) (result f64))"
, "(func $clean_lnR (import \"clean\" \"lnR\") (param f64) (result f64))"
, "(func $clean_log10R (import \"clean\" \"log10R\") (param f64) (result f64))"
, "(func $clean_RtoAC_words_needed (import \"clean\" \"RtoAC_words_needed\") (param f64) (result i32))"
, "(func $clean_RtoAC (import \"clean\" \"RtoAC\") (param i32 f64) (result i32))"
, "(func $clean_RtoAC (import \"clean\" \"RtoAC\") (param f64 i32) (result i32))"
, if debug_instructions "(func $clean_debug_instr (import \"clean\" \"debug_instr\") (param i32 i32))" ""
// For illegal instructions, first the handler is called with arguments (pc,instr,asp,bsp,csp,hp,hp-free).
// If the result is zero, clean_illegal_instr is called with (pc,instr) and interpretation stops.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment