Class: CastOff::Compiler::SimpleIR::GuardIR
- Defined in:
- lib/cast_off/compile/ir/guard_ir.rb
Direct Known Subclasses
Constant Summary collapse
- GUARD_DEOPTIMIZATION_TEMPLATE =
ERB.new(" /* depth = <%= @insn.depth %> */\n% @information.undefined_variables.each do |var|\n% @insn.iseq.initialize_for_guards(var) if var.is_a?(LocalVariable)\n% end\n% top = @insn.iseq\n% a = [@insn.iseq]\n% a = @insn.iseq.ancestors.reverse + a if @translator.inline_block?\n% a.each_with_index do |s, idx|\n {\n% bug() unless @dependent_local_variables[s]\n% bug() unless @dependent_stack_variables[s]\n% local_c = @dependent_local_variables[s].size()\n% stack_c = @dependent_stack_variables[s].size()\n% if @translator.inline_block?\n int local_c = <%= local_c %>;\n VALUE local_v[<%= local_c %>];\n% end\n int stack_c = <%= stack_c %>;\n VALUE stack_v[<%= stack_c %>];\n rb_iseq_t *iseq = <%= s %>;\n% @dependent_local_variables[s].each_with_index do |v, i|\n% if @translator.inline_block?\n local_v[<%= i %>] = <%= get_variable(v).boxed_form %>;\n% end\n% end\n% @dependent_stack_variables[s].each_with_index do |v, i|\n stack_v[<%= i %>] = <%= get_variable(v).boxed_form %>;\n% end\n% method_p = (s.itype == :method ? 1 : 0)\n% lambda_p = (s.itype == :method ? 0 : 'lambda_p')\n% top_p = (top == s ? 1 : 0)\n% bottom_p = (s.root? ? 1 : 0)\n% if @translator.inline_block?\n% if s.root?\n thval = rb_thread_current();\n th = DATA_PTR(thval);\n specval = 0;\n lfp = 0;\n dfp = 0;\n% else\n <%= s.loopkey.dopt_func %>(&<%= s.loopkey %>, specval);\n% end\n% if s == top\n return cast_off_deoptimize_inline(self, iseq, NULL, pc, local_c, local_v, stack_c, stack_v, <%= top_p %>, <%= bottom_p %>, <%= method_p %>, lfp, dfp);\n% else\n% bug() unless idx + 1 < a.size\n% biseq = a[idx + 1]\n% bug() unless biseq.parent_pc\n specval = cast_off_deoptimize_inline(self, iseq, <%= biseq %>, <%= biseq.parent_pc %>, local_c, local_v, stack_c, stack_v, <%= top_p %>, <%= bottom_p %>, <%= method_p %>, lfp, dfp);\n% if s.root?\n lfp = th->cfp->lfp;\n% end\n dfp = th->cfp->dfp;\n% end\n% else\n {\nVALUE return_value = cast_off_deoptimize_noinline(self, iseq, pc, stack_c, stack_v, <%= method_p %>, <%= lambda_p %>, <%= s.parent_pc ? s.parent_pc : -1 %>);\n% if s.catch_exception?\nTH_POP_TAG2();\n% end\nreturn return_value;\n }\n% end\n }\n% end\n rb_bug(\"should not be reached\");\n", 0, '%-', 'g2')
- GUARD_EXCEPTION_FUNCTION_TEMPLATE =
ERB.new("NORETURN(static inline int <THROW_EXCEPTION_FUNCTION_NAME>(VALUE obj));\nstatic inline int <THROW_EXCEPTION_FUNCTION_NAME>(VALUE obj)\n{\n VALUE path0 = rb_class_path(rb_class_of(obj));\n VALUE path1 = rb_class_path(rb_obj_class(obj));\n rb_raise(rb_eCastOffExecutionError, \"\\\\\ntype mismatch: guard(<%= @guard_value %>:<%= \"\\\#{@insn.pc}: \\\#{@insn.op}, depth = \\\#{@insn.depth}\" %>)\\\\n\\\\\nname = <%= @insn.iseq.name %>, line = <%= @source_line %>: source = %s\\\\n\\\\\nexpected <%= @guard_value.types %> but %s, %s\\\\n\\\\\n<%= @translator.target_name() %>\", <%= @source.to_s.inspect %>, RSTRING_PTR(path0), RSTRING_PTR(path1));\n}\n", 0, '%-', 'g1')
- GUARD_RECOMPILATION_FUNCTION_TEMPLATE =
ERB.new("NOINLINE(static void <RECOMPILATION_FUNCTION_NAME>(VALUE obj));\nstatic void <RECOMPILATION_FUNCTION_NAME>(VALUE obj)\n{\n#if 1\n if(!sampling_table) register_sampling_table(rb_hash_new());\n% count = 0\n% done = []\n% queue = [@guard_value]\n% while (val = queue.pop)\n% bug() if done.include?(val)\n% done << val\n% bug() unless val.is_a?(Variable)\n% defs = get_definition(val)\n% defs.each do |defn|\n% case defn\n% when SubIR\n% case defn.src\n% when LocalVariable, DynamicVariable, InstanceVariable, ClassVariable, GlobalVariable, Self\n% count += 1\n sampling_variable(obj, ID2SYM(rb_intern(\"<%= defn.src.source %>\")));\n% if !queue.include?(defn.src) && !done.include?(defn.src)\n% dlog(\"add recompilation queue \\\#{defn.src}\")\n% queue << defn.src\n% end\n% when ConstWrapper\n% # Fixme\n /* <%= defn.src.path %> */\n% when Literal, Argument, TmpBuffer\n% # nothing to do\n% else\n% bug(defn.src)\n% end\n% when InvokeIR\n% recv = defn.param_variables.first\n% if recv.dynamic?\n% bug() if val == @guard_value\n% next\n% end\n% recv.types.each do |k|\n% recv_class = @translator.get_c_classname(k)\n% bug() unless recv_class\n% count += 1\n __sampling_poscall(obj, <%= recv_class %>, ID2SYM(rb_intern(\"<%= defn.method_id %>\")));\n% end\n% end\n% end\n% end\n% if count > 0\n rb_funcall(rb_mCastOff, rb_intern(\"re_compile\"), 2, rb_str_new2(\"<%= @translator.signiture() %>\"), sampling_table_val);\n% else\n% dlog(\"skip recompilation: defs = \\\#{defs.join(\"\\\\n\")}\")\n% end\n#endif\n}\n", 0, '%-', '__recompilation')
- GUARD_TEMPLATE =
ERB.new("%bug() if @guard_value.undefined? || @guard_value.dynamic?\n<%= guard_begin() %>\n%func = @translator.declare_recompilation_function(GUARD_RECOMPILATION_FUNCTION_TEMPLATE.trigger(binding))\n <%= func %>(<%= @guard_value %>);\n%if @configuration.deoptimize?\n goto <%= @insn.guard_label %>;\n% @insn.iseq.inject_guard(@insn, GUARD_DEOPTIMIZATION_TEMPLATE.trigger(binding))\n%else\n% func = @translator.declare_throw_exception_function(GUARD_EXCEPTION_FUNCTION_TEMPLATE.trigger(binding))\n <%= func %>(<%= guard_value %>);\n%end\n<%= guard_end() %>\n", 0, '%-', 'g0')
- GUARD_CHECK_TEMPLATE =
ERB.new("%if @guard_value.is_just?(NilClass)\n if (UNLIKELY(!NIL_P(<%= @guard_value %>))) {\n%elsif @guard_value.is_just?(TrueClass)\n if (UNLIKELY(<%= @guard_value %> != Qtrue)) {\n%elsif @guard_value.is_just?(FalseClass)\n if (UNLIKELY(<%= @guard_value %> != Qfalse)) {\n%elsif @guard_value.is_just?(Symbol)\n if (UNLIKELY(!SYMBOL_P(<%= @guard_value %>))) {\n%elsif @guard_value.is_just?(Fixnum)\n if (UNLIKELY(!FIXNUM_P(<%= @guard_value %>))) {\n%else\n% if simple?\n% func = @translator.declare_class_check_function(CLASS_CHECK_FUNCTION_TEMPLATE_SIMPLE.trigger(binding))\n if (UNLIKELY(!<%= func %>(<%= @guard_value %>))) {\n% else\n% func = @translator.declare_class_check_function(CLASS_CHECK_FUNCTION_TEMPLATE_COMPLEX.trigger(binding))\n if (UNLIKELY(!<%= func %>(<%= @guard_value %>, rb_class_of(<%= @guard_value %>)))) {\n% end\n%end\n\n", 0, '%-', 'g3')
- CLASS_CHECK_FUNCTION_TEMPLATE_SIMPLE =
ERB.new("static inline int <CLASS_CHECK_FUNCTION_NAME>(VALUE obj)\n{\n if (0) {\n%if @guard_value.is_also?(NilClass)\n } else if (NIL_P(obj)) {\n return 1;\n%end\n%if @guard_value.is_also?(TrueClass)\n } else if (obj == Qtrue) {\n return 1;\n%end\n%if @guard_value.is_also?(FalseClass)\n } else if (obj == Qfalse) {\n return 1;\n%end\n%if @guard_value.is_also?(Symbol)\n } else if (SYMBOL_P(obj)) {\n return 1;\n%end\n%if @guard_value.is_also?(Fixnum)\n } else if (FIXNUM_P(obj)) {\n return 1;\n%end\n } else {\n return 0;\n }\n}\n", 0, '%-', 'g4')
- CLASS_CHECK_FUNCTION_TEMPLATE_COMPLEX =
ERB.new("NOINLINE(static int <CLASS_CHECK_FUNCTION_NAME>_failed(VALUE obj, VALUE klass));\n\nstatic inline int <CLASS_CHECK_FUNCTION_NAME>(VALUE obj, VALUE klass)\n{\n if (0) {\n% @guard_value.types.each do |klass|\n% name = @translator.get_c_classname(klass)\n% raise(CompileError.new(\"can't generate guard for \\\#{klass}, you should pass binding to CastOff (\\\#{klass.singleton? ? 1 : 0})\")) unless name\n } else if (LIKELY(klass == <%= name %>)) {\n return 1;\n% end\n } else {\n if (LIKELY(<CLASS_CHECK_FUNCTION_NAME>_failed(obj, klass))) {\nreturn 1;\n } else {\nreturn 0;\n }\n }\n}\n\nstatic int <CLASS_CHECK_FUNCTION_NAME>_failed(VALUE obj, VALUE klass)\n{\n if (UNLIKELY(FL_TEST(klass, FL_SINGLETON) && empty_method_table_p(klass))) {\n return <CLASS_CHECK_FUNCTION_NAME>(obj, rb_obj_class(obj));\n }\n return 0;\n}\n", 0, '%-', 'g4')
Instance Attribute Summary collapse
-
#guard_value ⇒ Object
readonly
Returns the value of attribute guard_value.
-
#result_variable ⇒ Object
readonly
Returns the value of attribute result_variable.
-
#values ⇒ Object
readonly
Returns the value of attribute values.
-
#variables ⇒ Object
readonly
Returns the value of attribute variables.
-
#variables_without_result ⇒ Object
readonly
Returns the value of attribute variables_without_result.
Attributes inherited from IR
Instance Method Summary collapse
-
#initialize(val, vars, insn, cfg) ⇒ GuardIR
constructor
A new instance of GuardIR.
- #mark(defs) ⇒ Object
- #propergate_boxed_value(defs) ⇒ Object
-
#propergate_exact_class(defs) ⇒ Object
unboxing end ###.
- #to_c ⇒ Object
- #type_propergation(defs) ⇒ Object
-
#unboxing_prelude ⇒ Object
unboxing begin ###.
Methods inherited from IR
#add_sampling_variable, #alive, #alive?, #dispatch_method?, #generate_guard, #get_definition, #get_definition_str, #get_usage, #get_variable, #inlining_target?, #propergate_guard_usage, #reset, #sampling_variable, #set_info, #standard_guard_target, #vanish, #vanish?
Methods included from Util
Constructor Details
#initialize(val, vars, insn, cfg) ⇒ GuardIR
Returns a new instance of GuardIR.
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/cast_off/compile/ir/guard_ir.rb', line 247 def initialize(val, vars, insn, cfg) super(insn, cfg) @guard_value = val bug() unless @guard_value.is_a?(Variable) @values = [@guard_value] @variables = [] @variables_without_result = [] @variables << @guard_value @variables_without_result << @guard_value @result_variable = nil @source = @insn.source @source = @source.empty? ? nil : @source @source_line = @insn.line.to_s if @configuration.deoptimize? @dependent_local_variables = get_dependent_local_variables(vars) @dependent_stack_variables = get_dependent_stack_variables(vars) @dependent_variables = @dependent_local_variables.values.flatten + @dependent_stack_variables.values.flatten end end |
Instance Attribute Details
#guard_value ⇒ Object (readonly)
Returns the value of attribute guard_value.
7 8 9 |
# File 'lib/cast_off/compile/ir/guard_ir.rb', line 7 def guard_value @guard_value end |
#result_variable ⇒ Object (readonly)
Returns the value of attribute result_variable.
7 8 9 |
# File 'lib/cast_off/compile/ir/guard_ir.rb', line 7 def result_variable @result_variable end |
#values ⇒ Object (readonly)
Returns the value of attribute values.
7 8 9 |
# File 'lib/cast_off/compile/ir/guard_ir.rb', line 7 def values @values end |
#variables ⇒ Object (readonly)
Returns the value of attribute variables.
7 8 9 |
# File 'lib/cast_off/compile/ir/guard_ir.rb', line 7 def variables @variables end |
#variables_without_result ⇒ Object (readonly)
Returns the value of attribute variables_without_result.
7 8 9 |
# File 'lib/cast_off/compile/ir/guard_ir.rb', line 7 def variables_without_result @variables_without_result end |
Instance Method Details
#mark(defs) ⇒ Object
319 320 321 322 323 324 325 326 327 328 329 330 331 |
# File 'lib/cast_off/compile/ir/guard_ir.rb', line 319 def mark(defs) if !@alive @alive = true defs.mark(@guard_value) if @configuration.deoptimize? bug() unless @dependent_variables @dependent_variables.each{|v| defs.mark(v)} end true else false end end |
#propergate_boxed_value(defs) ⇒ Object
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'lib/cast_off/compile/ir/guard_ir.rb', line 272 def propergate_boxed_value(defs) change = false # forward change |= defs.propergate_boxed_value_forward(@guard_value) # backward if @guard_value.boxed? change |= defs.propergate_boxed_value_backward(@guard_value) if @configuration.deoptimize? bug() unless @dependent_variables @dependent_variables.each do |var| if var.is_a?(DynamicVariable) bug() unless var.boxed? next end vars = defs.get_variables(var) boxed_p = !!vars.find{|v| v.boxed?} next unless boxed_p vars.each do |v| change |= v.box() change |= defs.propergate_boxed_value_backward(v) end end end end change end |
#propergate_exact_class(defs) ⇒ Object
unboxing end ###
303 304 305 |
# File 'lib/cast_off/compile/ir/guard_ir.rb', line 303 def propergate_exact_class(defs) defs.exact_class_resolve(@guard_value) end |
#to_c ⇒ Object
307 308 309 310 311 312 313 |
# File 'lib/cast_off/compile/ir/guard_ir.rb', line 307 def to_c() if @configuration.inject_guard? && !@guard_value.class_exact? bug() if @insn.pc == -1 bug() unless @insn.depth GUARD_TEMPLATE.trigger(binding).chomp end end |
#type_propergation(defs) ⇒ Object
315 316 317 |
# File 'lib/cast_off/compile/ir/guard_ir.rb', line 315 def type_propergation(defs) bug() end |
#unboxing_prelude ⇒ Object
unboxing begin ###
268 269 270 |
# File 'lib/cast_off/compile/ir/guard_ir.rb', line 268 def unboxing_prelude() @guard_value.box() unless @guard_value.class_exact? && @guard_value.can_unbox? end |