Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
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...
commit 2c097854fdca724f58977dc8ceef00b4636138ac 1 parent b2bf8de
@brixen brixen authored
View
16 rakelib/vm.rake
@@ -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"
View
15 vm/accessor_primitives.cpp
@@ -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"
+}
View
176 vm/codegen/field_extract.rb
@@ -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
View
23 vm/invoke_primitives.cpp
@@ -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
20 vm/jit_primitives.cpp
@@ -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"
+}
View
24 vm/primitives.cpp → vm/method_primitives.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"
}
Please sign in to comment.
Something went wrong with that request. Please try again.