Open vouillon opened 10 years ago
One more PR that might break js_of_ocaml. see comment https://github.com/ocaml/ocaml/pull/14#issuecomment-35822033
What about more debug (event) information ?
What do you mean?
could we improve sourcemap generation with more debug information ?
Do you have anything specific in mind? I would say we already have all the needed information: for code with debugg information, we should be able to associate to any bytecode instruction a corresponding location in the source code.
Code like let rec f x y = 1 and z = Some (f, h)
is compiled using primitive caml_alloc_dummy
to allocate a block (for all values but floats, including closures), then caml_update_dummy
to fill the block with its actual contents. So we have a hack in Js_of_ocaml to be able to use a block (a JavaScript array), as if it was a function.
It would be better if a specific primitive caml_alloc_dummy_closure
was used to allocate dummy closures. Even better, this primitive could be given the arity of the closure. Then, we could compile
a primitive call caml_alloc_dummy_function(2)
into a function function f(x,y) {return f.fun(x,y); }
which does not need any specific runtime support.
I'm wondering whether we could do something for recursive modules as well. At the moment, we have a hack that replaces the bytecode implementation of CamlinternalMod by a JavaScript implementation.
caml_alloc_dummy_closure => https://github.com/hhugo/ocaml/compare/jsoo_friendly
limits due to runtime representation should/could be set from the runtime.
Sys.max_array_length
Sys.int_size
(new)If String.copy
and (^)
were implemented as primitive, we could more easily generate efficient code for them.
OCaml is switching to immutable strings. However, as they are implemented imperatively, based on byte sequence operations, there does not seem to be any easy way to take advantage of this.
We should probably map OCaml values to JavaScript objects rather than JavaScript arrays. Indeed, this is more memory efficient (V8 has a high overhead for arrays; the block tag would not need to be stored in the object) and potentially faster (no need for bound check when accessing fields).
However, the same bytecode instruction MAKEBLOCK
is used for allocating both arrays and blocks.
How would you compile OCaml value to Js Object ? One constructor per tag and size couple ?
@vouillon, a quick experiment with compiling ocaml blocks to Js objects shows poor performances. x2.5 slower on @jordwalke example.
(deriving and marshall not updated) https://github.com/ocsigen/js_of_ocaml/tree/caml_block https://github.com/hhugo/ocaml/tree/make_array
This is because you are using numeric fields. Here is what I get by manually tweaking the JavaScript output:
Arrays | Objects (numeric fields) | Objects (non-numeric fields) | |
---|---|---|---|
V8 | 180 | 500 | 125 |
JSC | 86 | 150 | 83 |
Spidermonkey | 170 | 300 | 82 |
I've update the code (regression inside) to use non-numeric fields. It's better but still a little bit slower than the current implem.
Which JavaScript engine did you try? Which version?
this is very interesting discussion, @vouillon , how did you get such numbers? btw, it is not always correct to compile blocks and arrays differently, since some internal hacks of the compiler treat array and object in a uniform way
That's the timings for a single program, that I manually rewrote.
You're right that for making this work the OCaml compiler would have to be modified.
If
String.copy
and(^)
were implemented as primitive, we could more easily generate efficient code for them.
I believe we are now closer to optimize theses string operations (xlink #977 #976 #924)
de implementation of CamlinternalMod by a JavaScript implementation.
This is now gone
I have recently proposed to change the definition of
Pervasives.min/max_int
so that Js_of_ocaml does not have to patch the bytecode (ocaml/ocaml#19). I'm wondering what other changes we could propose that would be useful to Js_of_ocaml.Pervasives.min/max_int
caml_alloc_dummy_closure
Sys.int_size
Sys.max_array_length