Skip to content

Commit

Permalink
Add support for unboxed constants
Browse files Browse the repository at this point in the history
Right now, unboxed constants are also boxed, but we choose to use the
unboxed variant when we know we don't need a boxed value. In short, this
allows for slightly faster math when working with constants.
  • Loading branch information
jeaye committed Apr 2, 2023
1 parent 86e0ff8 commit b557dcb
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 17 deletions.
5 changes: 4 additions & 1 deletion include/cpp/jank/analyze/local_frame.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ namespace jank::analyze
runtime::obj::symbol_ptr var_name{};
};

/* TODO: Track constant usages to figure out if boxing is needed at all,
* rather than just doing both. */
struct lifted_constant
{
runtime::obj::symbol native_name;
option<runtime::obj::symbol> unboxed_native_name;
runtime::object_ptr data{};
};

Expand Down Expand Up @@ -58,7 +61,7 @@ namespace jank::analyze

/* This is used to find both captures and regular locals, since it's
* impossible to know which one a sym is without finding it. */
option<find_result> find_capture(runtime::obj::symbol_ptr const &sym);
option<find_result> find_capture(runtime::obj::symbol_ptr sym);
static void register_captures(find_result const &result);

runtime::obj::symbol_ptr lift_var(runtime::obj::symbol_ptr const &);
Expand Down
14 changes: 10 additions & 4 deletions src/cpp/jank/analyze/local_frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace jank::analyze
return *this;
}

option<local_frame::find_result> local_frame::find_capture(runtime::obj::symbol_ptr const &sym)
option<local_frame::find_result> local_frame::find_capture(runtime::obj::symbol_ptr const sym)
{
decltype(local_frame::find_result::crossed_fns) crossed_fns;

Expand Down Expand Up @@ -111,18 +111,24 @@ namespace jank::analyze
return none;
}

void local_frame::lift_constant(runtime::object_ptr constant)
void local_frame::lift_constant(runtime::object_ptr const constant)
{
auto &closest_fn(find_closest_fn_frame(*this));
auto const &found(closest_fn.lifted_constants.find(constant));
if(found != closest_fn.lifted_constants.end())
{ return; }
lifted_constant l{ runtime::context::unique_symbol("const"), constant };

auto name(runtime::context::unique_symbol("const"));
option<runtime::obj::symbol> unboxed_name;
if(constant->as_number())
{ unboxed_name = runtime::obj::symbol{ name.ns, name.name + "__unboxed" }; }

lifted_constant l{ std::move(name), std::move(unboxed_name), constant };
closest_fn.lifted_constants.emplace(constant, std::move(l));
}

option<std::reference_wrapper<lifted_constant const>> local_frame::find_lifted_constant
(runtime::object_ptr o) const
(runtime::object_ptr const o) const
{
auto const &closest_fn(find_closest_fn_frame(*this));
auto const &found(closest_fn.lifted_constants.find(o));
Expand Down
53 changes: 41 additions & 12 deletions src/cpp/jank/codegen/processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,24 @@ namespace jank::codegen
constexpr native_string_view const recur_suffix{ "__recur" };

/* TODO: Consider making this a virtual fn on object, to return the C++ name. */
native_string_view gen_constant_type(runtime::object_ptr const o)
native_string_view gen_constant_type(runtime::object_ptr const o, bool const boxed)
{
if(o->as_nil())
{ return "jank::runtime::obj::nil_ptr"; }
else if(auto const * const d = o->as_boolean())
{ return "jank::runtime::obj::boolean_ptr"; }
else if(auto const * const d = o->as_integer())
{ return "jank::runtime::obj::integer_ptr"; }
{
if(boxed)
{ return "jank::runtime::obj::integer_ptr"; }
return "jank::native_integer";
}
else if(auto const * const d = o->as_real())
{ return "jank::runtime::obj::real_ptr"; }
{
if(boxed)
{ return "jank::runtime::obj::real_ptr"; }
return "jank::native_real";
}
else if(auto const * const d = o->as_symbol())
{ return "jank::runtime::obj::symbol_ptr"; }
else if(auto const * const d = o->as_keyword())
Expand All @@ -80,8 +88,14 @@ namespace jank::codegen
{ return "jank::runtime::object_ptr"; }
}

void gen_constant(runtime::object_ptr const o, fmt::memory_buffer &buffer)
void gen_constant(runtime::object_ptr const o, fmt::memory_buffer &buffer, bool const boxed)
{
if(!boxed)
{
o->to_string(buffer);
return;
}

auto inserter(std::back_inserter(buffer));
if(o->as_nil())
{ format_to(inserter, "jank::runtime::JANK_NIL"); }
Expand Down Expand Up @@ -129,7 +143,7 @@ namespace jank::codegen
for(auto const &form : d->data)
{
format_to(inserter, ", ");
gen_constant(form, buffer);
gen_constant(form, buffer, true);
}
format_to(inserter, ")");
}
Expand All @@ -143,7 +157,7 @@ namespace jank::codegen
{
if(need_comma)
{ format_to(inserter, ", "); }
gen_constant(form, buffer);
gen_constant(form, buffer, true);
need_comma = true;
}
format_to(inserter, ")");
Expand Down Expand Up @@ -517,14 +531,18 @@ namespace jank::codegen
(
analyze::expr::primitive_literal<analyze::expression> const &expr,
analyze::expr::function_arity<analyze::expression> const &,
bool const
bool const box_needed
)
{
auto const &constant(expr.frame->find_lifted_constant(expr.data).unwrap().get());
switch(expr.expr_type)
{
case analyze::expression_type::expression:
{ return constant.native_name.name; }
{
if(!box_needed && constant.unboxed_native_name.is_some())
{ return constant.unboxed_native_name.unwrap().name; }
return constant.native_name.name;
}
case analyze::expression_type::return_statement:
{
auto inserter(std::back_inserter(body_buffer));
Expand Down Expand Up @@ -910,14 +928,26 @@ namespace jank::codegen

for(auto const &v : arity.frame->lifted_constants)
{
/* TODO: More useful types here. */
format_to
(
inserter,
"{} const {};",
detail::gen_constant_type(v.second.data),
detail::gen_constant_type(v.second.data, true),
runtime::munge(v.second.native_name.name)
);

if(v.second.unboxed_native_name.is_some())
{
format_to
(
inserter,
"static constexpr {} const {}{{ ",
detail::gen_constant_type(v.second.data, false),
runtime::munge(v.second.unboxed_native_name.unwrap().name)
);
detail::gen_constant(v.second.data, header_buffer, false);
format_to(inserter, "}};");
}
}

/* TODO: More useful types here. */
Expand Down Expand Up @@ -966,7 +996,6 @@ namespace jank::codegen
);
}

/* TODO: Also generate unboxed constants for some types. */
for(auto const &v : arity.frame->lifted_constants)
{
format_to
Expand All @@ -975,7 +1004,7 @@ namespace jank::codegen
", {0}{{",
runtime::munge(v.second.native_name.name)
);
detail::gen_constant(v.second.data, header_buffer);
detail::gen_constant(v.second.data, header_buffer, true);
format_to(inserter, "}}");
}

Expand Down

0 comments on commit b557dcb

Please sign in to comment.