Permalink
Browse files

Split generated code for primitives.

The generated code is more than 45k sloc. This makes it difficult to
compile on memory constrained VMs and devices.
  • Loading branch information...
1 parent b2bf8de commit 2c097854fdca724f58977dc8ceef00b4636138ac @brixen brixen committed Feb 13, 2012
View
@@ -38,7 +38,13 @@ TYPE_GEN = %w[ vm/gen/includes.hpp
vm/gen/object_types.hpp
vm/gen/typechecks.gen.cpp
vm/gen/primitives_declare.hpp
- vm/gen/primitives_glue.gen.cpp ]
+ vm/gen/glue_functions.cpp
+ vm/gen/jit_functions.cpp
+ vm/gen/invoke_functions.cpp
+ vm/gen/accessor_functions.cpp
+ vm/gen/glue_resolver.cpp
+ vm/gen/jit_resolver.cpp
+ vm/gen/invoke_resolver.cpp ]
GENERATED = %W[ vm/gen/revision.h
vm/gen/config_variables.h
@@ -267,7 +273,13 @@ end
# Generate files for instructions and interpreters
-file 'vm/gen/primitives_glue.gen.cpp' => field_extract_headers
+file "gen/method_primitives.cpp" => field_extract_headers
+file "gen/jit_primitives.cpp" => field_extract_headers
+file "gen/invoke_primitives.cpp" => field_extract_headers
+file "gen/accessor_primitives.cpp" => field_extract_headers
+file "gen/method_resolver.cpp" => field_extract_headers
+file "gen/jit_resolver.cpp" => field_extract_headers
+file "gen/invoke_resolver.cpp" => field_extract_headers
iparser = InstructionParser.new "vm/instructions.def"
@@ -0,0 +1,15 @@
+#include "prelude.hpp"
+#include "vm.hpp"
+#include "primitives.hpp"
+#include "gen/includes.hpp"
+#include "arguments.hpp"
+#include "call_frame.hpp"
+
+#include "instruments/tooling.hpp"
+
+#include <iostream>
+
+namespace rubinius {
+
+#include "gen/accessor_primitives.cpp"
+}
@@ -1205,89 +1205,145 @@ def write_if_new(path)
end
end
-write_if_new "vm/gen/primitives_glue.gen.cpp" do |f|
- names = []
- jit_stubs = []
- invoke_stubs = []
+class PrimitiveCodeGenerator
+ def initialize(parser)
+ classes = parser.classes.sort_by { |n, | n }
- parser.classes.sort_by { |name,| name }.each do |n, cpp|
- cpp.primitives.sort_by { |name,| name }.each do |pn, prim|
- names << pn
+ @indexes = {}
+ @jit_functions = []
+ @invoke_functions = []
- f << prim.generate_glue
+ @names = []
+ @primitives = []
- if prim.respond_to?(:generate_jit_stub) and jit = prim.generate_jit_stub
- f << jit
- jit_stubs << [prim, pn]
- end
+ @files = classes.map do |n, file|
+ primitives = file.primitives.sort_by { |n, | n }
+ primitives.each { |n, p| @names << n }
- if prim.respond_to?(:generate_invoke_stub) and is = prim.generate_invoke_stub
- f << is
- invoke_stubs << [prim, pn]
- end
+ @names += file.access_primitives
+
+ @primitives += primitives
+ file
end
- f << cpp.generate_accessors
- names += cpp.access_primitives
+ @names.sort!
end
- f.puts "executor Primitives::resolve_primitive(STATE, Symbol* name, int* index) {"
+ def generate
+ method_primitives
+ jit_primitives
+ invoke_primitives
+ accessor_primitives
+ method_resolver
+ jit_resolver
+ invoke_resolver
+ end
+
+ def method_primitives
+ write_if_new "vm/gen/method_primitives.cpp" do |f|
+ @primitives.each { |_, p| f << p.generate_glue }
+ end
+ end
+
+ def jit_primitives
+ write_if_new "vm/gen/jit_primitives.cpp" do |f|
+ @primitives.each do |n, p|
+ if p.respond_to? :generate_jit_stub
+ code = p.generate_jit_stub
+ if code
+ f << code
+ @jit_functions << [n, p]
+ end
+ end
+ end
+ end
+ end
+
+ def invoke_primitives
+ write_if_new "vm/gen/invoke_primitives.cpp" do |f|
+ @primitives.each do |n, p|
+ if p.respond_to? :generate_invoke_stub
+ code = p.generate_invoke_stub
+ if code
+ f << code
+ @invoke_functions << [n, p]
+ end
+ end
+ end
+ end
+ end
+
+ def accessor_primitives
+ write_if_new "vm/gen/accessor_primitives.cpp" do |f|
+ @files.each { |file| f << file.generate_accessors }
+ end
+ end
- indexes = {}
+ def method_resolver
+ write_if_new "vm/gen/method_resolver.cpp" do |f|
+ f.puts "executor Primitives::resolve_primitive(STATE, Symbol* name, int* index) {"
- i = 0
- names.sort.each do |name|
- indexes[name] = i
+ @names.each_with_index do |name, index|
+ @indexes[name] = index
- f.puts <<-EOF
+ f.puts <<-EOC
if(name == state->symbol("#{name}")) {
- if(index) *index = #{i};
+ if(index) *index = #{index};
return &Primitives::#{name};
}
- EOF
-
- i += 1
- end
+ EOC
+ end
- f.puts <<-EOF
-// if(!state->probe()->nil_p()) {
-// state->probe()->missing_primitive(state, name->c_str(state));
-// }
-return &Primitives::unknown_primitive;
-// commented out while we have soft primitive failures
-// throw std::runtime_error(msg.c_str());
+ f.puts <<-EOC
+ // if(!state->probe()->nil_p()) {
+ // state->probe()->missing_primitive(state, name->c_str(state));
+ // }
+ return &Primitives::unknown_primitive;
+ // commented out while we have soft primitive failures
+ // throw std::runtime_error(msg.c_str());
}
- EOF
-
- f.puts "bool Primitives::get_jit_stub(int index, JITStubResults& res) {"
- f.puts " switch(index) {"
-
- jit_stubs.each do |prim, name|
- f.puts " case #{indexes[name]}: // #{name}"
- f.puts " res.set_arg_count(#{prim.arg_count});"
- f.puts " res.set_name(\"jit_stub_#{name}\");"
- f.puts " res.set_pass_callframe(false);" if prim.safe
- f.puts " res.set_can_fail(false);" if !prim.can_fail
- f.puts " return true;"
+ EOC
+ end
end
- f.puts " }"
+ def jit_resolver
+ write_if_new "vm/gen/jit_resolver.cpp" do |f|
+ f.puts "bool Primitives::get_jit_stub(int index, JITStubResults& res) {"
+ f.puts " switch(index) {"
+
+ @jit_functions.each do |n, p|
+ f.puts " case #{@indexes[n]}: // #{n}"
+ f.puts " res.set_arg_count(#{p.arg_count});"
+ f.puts " res.set_name(\"jit_stub_#{n}\");"
+ f.puts " res.set_pass_callframe(false);" if p.safe
+ f.puts " res.set_can_fail(false);" unless p.can_fail
+ f.puts " return true;"
+ end
- f.puts " return false;"
+ f.puts " }"
+ f.puts " return false;"
+ f.puts "}"
+ end
+ end
- f.puts "}"
+ def invoke_resolver
+ write_if_new "vm/gen/invoke_resolver.cpp" do |f|
+ f.puts "InvokePrimitive Primitives::get_invoke_stub(STATE, Symbol* name) {"
- f.puts "InvokePrimitive Primitives::get_invoke_stub(STATE, Symbol* name) {"
- invoke_stubs.each do |prim, name|
- f.puts <<-EOF
- if(name == state->symbol("#{name}")) {
- return &invoke_#{name};
+ @invoke_functions.each do |n, |
+ f.puts <<-EOC
+ if(name == state->symbol("#{n}")) {
+ return &invoke_#{n};
}
- EOF
- end
+ EOC
+ end
- f.puts " return &invoke_unknown_primitive;"
- f.puts "}"
+ f.puts " return &invoke_unknown_primitive;"
+ f.puts "}"
+ end
+ end
end
+
+PrimitiveCodeGenerator.new(parser).generate
@@ -0,0 +1,23 @@
+#include "prelude.hpp"
+#include "vm.hpp"
+#include "primitives.hpp"
+#include "gen/includes.hpp"
+#include "arguments.hpp"
+#include "call_frame.hpp"
+
+#include "instruments/tooling.hpp"
+
+#include <iostream>
+
+namespace rubinius {
+
+extern "C" Object* invoke_unknown_primitive(STATE, CallFrame* call_frame,
+ Object** args, int arg_count)
+{
+ Exception::internal_error(state, call_frame, "unable to invoke primitive");
+ return 0;
+}
+
+#include "gen/invoke_primitives.cpp"
+#include "gen/invoke_resolver.cpp"
+}
View
@@ -0,0 +1,20 @@
+#include "prelude.hpp"
+#include "vm.hpp"
+#include "primitives.hpp"
+#include "gen/includes.hpp"
+#include "arguments.hpp"
+#include "call_frame.hpp"
+
+#include "instruments/tooling.hpp"
+
+#include <iostream>
+
+#ifdef ENABLE_LLVM
+#include "llvm/state.hpp"
+#endif
+
+namespace rubinius {
+
+#include "gen/jit_primitives.cpp"
+#include "gen/jit_resolver.cpp"
+}
@@ -15,13 +15,6 @@
namespace rubinius {
-#ifdef ENABLE_LLVM
- void Primitives::queue_for_jit(STATE, CallFrame* call_frame, int which) {
- // LLVMState* ls = LLVMState::get(state);
- // ls->compile_callframe(state, 0, call_frame, which);
- }
-#endif
-
Object* Primitives::unknown_primitive(STATE, CallFrame* call_frame, Executable* exec, Module* mod, Arguments& args) {
std::string message = std::string("Called unbound or invalid primitive from method name: ");
message += args.name()->to_str(state)->c_str(state);
@@ -31,6 +24,13 @@ namespace rubinius {
return cNil;
}
+#ifdef ENABLE_LLVM
+ void Primitives::queue_for_jit(STATE, CallFrame* call_frame, int which) {
+ // LLVMState* ls = LLVMState::get(state);
+ // ls->compile_callframe(state, 0, call_frame, which);
+ }
+#endif
+
static inline void check_counter(STATE, CallFrame* call_frame, int which) {
#ifdef ENABLE_LLVM
int& hits = state->shared().primitive_hits(which);
@@ -41,12 +41,6 @@ namespace rubinius {
#endif
}
-extern "C" Object* invoke_unknown_primitive(STATE, CallFrame* call_frame,
- Object** args, int arg_count)
-{
- Exception::internal_error(state, call_frame, "unable to invoke primitive");
- return 0;
-}
-
-#include "gen/primitives_glue.gen.cpp"
+#include "gen/method_primitives.cpp"
+#include "gen/method_resolver.cpp"
}

0 comments on commit 2c09785

Please sign in to comment.