rubymirrors 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. data/Gemfile +7 -0
  2. data/README.md +30 -0
  3. data/Rakefile +13 -0
  4. data/lib/abstract_reflection.rb +112 -0
  5. data/lib/abstract_reflection/class_mirror.rb +150 -0
  6. data/lib/abstract_reflection/compiler_mirror.rb +31 -0
  7. data/lib/abstract_reflection/field_mirror.rb +35 -0
  8. data/lib/abstract_reflection/gc_mirror.rb +19 -0
  9. data/lib/abstract_reflection/method_mirror.rb +253 -0
  10. data/lib/abstract_reflection/mirror.rb +108 -0
  11. data/lib/abstract_reflection/object_mirror.rb +48 -0
  12. data/lib/abstract_reflection/stack_frame_mirror.rb +61 -0
  13. data/lib/abstract_reflection/thread_mirror.rb +64 -0
  14. data/lib/maglev/reflection.rb +49 -0
  15. data/lib/maglev/reflection/class_mirror.rb +157 -0
  16. data/lib/maglev/reflection/core_ext/class_organizer.rb +20 -0
  17. data/lib/maglev/reflection/core_ext/maglev.rb +5 -0
  18. data/lib/maglev/reflection/core_ext/method.rb +154 -0
  19. data/lib/maglev/reflection/core_ext/module.rb +41 -0
  20. data/lib/maglev/reflection/core_ext/object.rb +4 -0
  21. data/lib/maglev/reflection/core_ext/thread.rb +226 -0
  22. data/lib/maglev/reflection/field_mirror.rb +39 -0
  23. data/lib/maglev/reflection/field_mirror/fixed_instance_variable_mirror.rb +25 -0
  24. data/lib/maglev/reflection/method_mirror.rb +149 -0
  25. data/lib/maglev/reflection/mirror.rb +6 -0
  26. data/lib/maglev/reflection/object_mirror.rb +18 -0
  27. data/lib/maglev/reflection/stack_frame_mirror.rb +104 -0
  28. data/lib/maglev/reflection/thread_mirror.rb +116 -0
  29. data/lib/rubinius/reflection.rb +6 -0
  30. data/lib/ruby/reflection.rb +74 -0
  31. data/lib/ruby/reflection/class_mirror.rb +89 -0
  32. data/lib/ruby/reflection/field_mirror.rb +32 -0
  33. data/lib/ruby/reflection/field_mirror/class_variable_mirror.rb +25 -0
  34. data/lib/ruby/reflection/field_mirror/constant_mirror.rb +36 -0
  35. data/lib/ruby/reflection/field_mirror/instance_variable_mirror.rb +25 -0
  36. data/lib/ruby/reflection/method_mirror.rb +122 -0
  37. data/lib/ruby/reflection/mirror.rb +12 -0
  38. data/lib/ruby/reflection/object_mirror.rb +25 -0
  39. data/lib/ruby/reflection/stack_frame_mirror.rb +49 -0
  40. data/lib/ruby/reflection/support/shift_reset.rb +29 -0
  41. data/lib/ruby/reflection/thread_mirror.rb +47 -0
  42. data/rubymirrors.gemspec +12 -0
  43. data/spec/class_spec.rb +92 -0
  44. data/spec/field_spec.rb +119 -0
  45. data/spec/fixtures/class_spec.rb +29 -0
  46. data/spec/fixtures/field_spec.rb +9 -0
  47. data/spec/fixtures/method_spec.rb +14 -0
  48. data/spec/fixtures/object_spec.rb +5 -0
  49. data/spec/fixtures/reflect_spec.rb +14 -0
  50. data/spec/fixtures/stack_frame_spec.rb +5 -0
  51. data/spec/fixtures/thread_spec.rb +5 -0
  52. data/spec/frame_spec.rb +80 -0
  53. data/spec/method_spec.rb +166 -0
  54. data/spec/object_spec.rb +18 -0
  55. data/spec/reflection_spec.rb +74 -0
  56. data/spec/spec_helper.rb +16 -0
  57. data/spec/spec_helper/mspec_patch.rb +29 -0
  58. data/spec/spec_helper/multiple_reflections.rb +14 -0
  59. data/spec/thread_spec.rb +142 -0
  60. metadata +173 -0
@@ -0,0 +1,39 @@
1
+ require 'ruby/reflection/field_mirror/class_variable_mirror'
2
+ require 'ruby/reflection/field_mirror/instance_variable_mirror'
3
+ require 'ruby/reflection/field_mirror/constant_mirror'
4
+ require 'maglev/reflection/field_mirror/fixed_instance_variable_mirror'
5
+
6
+ module Maglev
7
+ class Reflection
8
+ class FieldMirror < Mirror
9
+ include AbstractReflection::FieldMirror
10
+ Field = Struct.new(:object, :name)
11
+ reflect! Field
12
+
13
+ def self.mirror_class(field)
14
+ if reflects?(field)
15
+ case
16
+ when field.name.start_with?("@@")
17
+ Ruby::Reflection::ClassVariableMirror
18
+ when field.name.start_with?("@")
19
+ Ruby::Reflection::InstanceVariableMirror
20
+ when field.name === Symbol
21
+ FixedInstanceVariableMirror
22
+ else
23
+ Ruby::Reflection::ConstantMirror
24
+ end
25
+ end
26
+ end
27
+
28
+ def initialize(obj)
29
+ super
30
+ @object = obj.object
31
+ @name = obj.name
32
+ end
33
+
34
+ def name
35
+ @name
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,25 @@
1
+ require 'maglev/reflection/core_ext/module'
2
+
3
+ module Maglev
4
+ class Reflection
5
+ class FixedInstanceVariableMirror < FieldMirror
6
+ def initialize(obj)
7
+ super
8
+ fixed_ivs = @object.__inst_var_names.to_a
9
+ @index = index(@name)
10
+ end
11
+
12
+ def public?
13
+ false
14
+ end
15
+
16
+ def protected?
17
+ false
18
+ end
19
+
20
+ def private?
21
+ true
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,149 @@
1
+ require 'maglev/reflection/core_ext/method'
2
+
3
+ module Maglev
4
+ class Reflection
5
+ class MethodMirror < Mirror
6
+ include AbstractReflection::MethodMirror
7
+ reflect! Method, UnboundMethod, GsNMethod
8
+
9
+ # Adding support for on-demand wrapping of GsNMethods
10
+ def initialize(obj)
11
+ super
12
+ if @subject.kind_of? GsNMethod
13
+ @subject = wrap_gsmeth(@subject)
14
+ end
15
+ end
16
+
17
+ def file
18
+ (@subject.source_location || [])[0]
19
+ end
20
+
21
+ def file=(string)
22
+ raise CapabilitiesExceeded unless regular_method?
23
+ reload_after do
24
+ defining_class.reflectee.class_eval(source, string, line)
25
+ end
26
+ end
27
+
28
+ def line
29
+ (@subject.source_location || [])[1]
30
+ end
31
+
32
+ def line=(num)
33
+ raise CapabilitiesExceeded unless regular_method?
34
+ reload_after do
35
+ defining_class.reflectee.class_eval(source, file, num)
36
+ end
37
+ end
38
+
39
+ def source
40
+ gsmeth.__source_string
41
+ end
42
+
43
+ def source=(str)
44
+ raise CapabilitiesExceeded unless regular_method?
45
+ reload_after do
46
+ if file.nil? && line.nil? # Smalltalk method
47
+ defining_class.reflectee.__compile_method_category_environment_id(str, '*maglev-dynamic-compile-unclassified', 1)
48
+ else # Ruby method
49
+ defining_class.reflectee.class_eval(str, file, line)
50
+ end
51
+ end
52
+ end
53
+
54
+ def selector
55
+ @subject.name.to_s
56
+ end
57
+
58
+ def defining_class
59
+ reflection.reflect gsmeth.__in_class
60
+ end
61
+
62
+ def arguments
63
+ gsmeth.__args_and_temps.to_a[0...gsmeth.__num_args].collect(&:to_s)
64
+ end
65
+
66
+ def block_argument
67
+ return nil unless gsmeth.__selector.to_s[-1] == ?&
68
+ arguments.last
69
+ end
70
+
71
+ def optional_arguments
72
+ opt_arg_offset = gsmeth.__ruby_opt_args_bits.to_s(2).reverse.index(?1)
73
+ argsize = gsmeth.__num_args
74
+ unless opt_arg_offset
75
+ if block_argument && splat_argument
76
+ opt_arg_offset = argsize - 2
77
+ elsif block_argument || splat_argument
78
+ opt_arg_offset = argsize - 1
79
+ else
80
+ opt_arg_offset = -2
81
+ end
82
+ end
83
+ arguments[opt_arg_offset..-1]
84
+ end
85
+
86
+ def required_arguments
87
+ arguments - optional_arguments
88
+ end
89
+
90
+ def splat_argument
91
+ return nil unless gsmeth.__selector.to_s[-2] == ?*
92
+ block_argument ? arguments[-2] : arguments[-1]
93
+ end
94
+
95
+ def step_offsets
96
+ gsmeth.__source_offsets
97
+ end
98
+
99
+ def send_offsets
100
+ offs = gsmeth.__source_offsets_of_sends.to_a
101
+ offs = offs.each_slice(2).collect do |offset, selector|
102
+ [prefix_if_ruby_selector(selector), offset]
103
+ end
104
+ Hash[*offs.flatten]
105
+ end
106
+
107
+ def bytecodes
108
+ gsmeth.__ip_steps.to_a.collect {|ip| gsmeth.__opcode_info_at(ip) }
109
+ end
110
+
111
+ def delete
112
+ raise CapabilitiesExceeded unless regular_method?
113
+ gsmeth.__in_class.remove_method(selector)
114
+ end
115
+
116
+ private
117
+ def wrap_gsmeth(gsmethod)
118
+ label = gsmethod.__name.to_s
119
+ cls = gsmethod.__in_class
120
+ if cls.instance_methods.include?(label)
121
+ cls.instance_method(label)
122
+ else
123
+ GsNMethodWrapper.new(gsmethod)
124
+ end
125
+ end
126
+
127
+ def gsmeth
128
+ @subject.__st_gsmeth
129
+ end
130
+
131
+ # Removes the Ruby suffix from the GsNMethod selector
132
+ def prefix_if_ruby_selector(sym)
133
+ selector = sym.to_s
134
+ selector[0...(selector.rindex(?#) || -1)]
135
+ end
136
+
137
+ def regular_method?
138
+ not (gsmeth.__is_method_for_block || gsmeth.__in_class.nil?)
139
+ end
140
+
141
+ def reload_after(&block)
142
+ cls = defining_class.reflectee
143
+ sel = selector.to_sym
144
+ yield
145
+ @subject = cls.instance_method(sel)
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,6 @@
1
+ module Maglev
2
+ class Reflection
3
+ class Mirror < Ruby::Reflection::Mirror
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,18 @@
1
+ module Maglev
2
+ class Reflection
3
+ class ObjectMirror < Ruby::Reflection::ObjectMirror
4
+ reflect! Object
5
+
6
+ private
7
+ def field_mirrors(list, subject = @subject)
8
+ list.collect do |name|
9
+ field_mirror(subject, name)
10
+ end
11
+ end
12
+
13
+ def field_mirror(subject, name)
14
+ reflection.reflect FieldMirror::Field.new(subject, name)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,104 @@
1
+ module Maglev
2
+ class Reflection
3
+ class StackFrameMirror < ObjectMirror
4
+ include AbstractReflection::StackFrameMirror
5
+ reflect! ThreadMirror::StackFrame
6
+
7
+ attr_reader :method
8
+
9
+ def initialize(obj)
10
+ super
11
+ @method = obj.method
12
+ @index = obj.index
13
+ @thread = obj.thread
14
+ end
15
+
16
+ def name
17
+ @method.selector
18
+ end
19
+
20
+ def receiver
21
+ reflection.reflect detailed_report[1]
22
+ end
23
+
24
+ def self
25
+ reflection.reflect detailed_report[2]
26
+ end
27
+
28
+ def selector
29
+ reflection.reflect detailed_report[3].to_s
30
+ end
31
+
32
+ def arguments
33
+ args_and_temps(0, num_args - 1)
34
+ end
35
+
36
+ def locals
37
+ args_and_temps(num_args, -1)
38
+ end
39
+
40
+ def step_offset
41
+ detailed_report[4]
42
+ end
43
+
44
+ def source_offset
45
+ detailed_report[5][step_offset - 1]
46
+ end
47
+
48
+ def variable_context
49
+ raise NotImplementedError, "TODO"
50
+ @thread.reflectee.__frame_contents_at(@index)[3]
51
+ end
52
+
53
+ def restart
54
+ @thread.reflectee.__trim_stack_to_level(@index)
55
+ true
56
+ end
57
+
58
+ def pop
59
+ @thread.reflectee.__trim_stack_to_level(@index + 1)
60
+ true
61
+ end
62
+
63
+ def step(*args)
64
+ @thread.step(*args)
65
+ true
66
+ end
67
+
68
+ def inspect
69
+ "#<#{self.class}: #{@index}: #{@method.defining_class}##{@method.name}>"
70
+ end
71
+
72
+ private
73
+ def detailed_report
74
+ @report ||= @thread.thread_report(@index)
75
+ end
76
+
77
+ def num_args
78
+ @method.arguments.size
79
+ end
80
+
81
+ def args_and_temps(from, to)
82
+ names = detailed_report[6][from..to].collect(&:to_s)
83
+ values = detailed_report[7][from..to].collect(&:to_s)
84
+ (values.size - names.size).times {|i| names << ".temp#{i+1}"}
85
+ values.map! {|v| reflection.reflect v }
86
+ FrameHash[names.zip(values)].tap {|o| o.frame = self }
87
+ end
88
+
89
+ class FrameHash < Hash
90
+ attr_writer :frame
91
+
92
+ def []=(key, value)
93
+ super
94
+ if @frame
95
+ @frame.thread.reflectee.__frame_at_temp_named_put(@frame.index,
96
+ key.to_s,
97
+ value)
98
+ end
99
+ end
100
+ end
101
+
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,116 @@
1
+ require 'maglev/reflection/core_ext/thread'
2
+ require 'maglev/reflection/core_ext/method'
3
+ require 'maglev/reflection/core_ext/maglev'
4
+ require 'maglev/objectlog'
5
+
6
+ module Maglev
7
+ class Reflection
8
+ class ThreadMirror < Ruby::Reflection::ThreadMirror
9
+ reflect! Thread
10
+ StackFrame = Struct.new :method, :index, :thread
11
+ ExceptionHandlers = {}
12
+
13
+ def self.copy_active_thread
14
+ save_thread("Continuation #{Thread.current}").continuation
15
+ end
16
+
17
+ def stack
18
+ @subject.__stack_depth.times.collect do |idx|
19
+ method = reflection.reflect @subject.__method_at(idx + 1)
20
+ frame = StackFrame.new method, idx + 1, self
21
+ StackFrameMirror.reflect frame, reflection
22
+ end
23
+ end
24
+
25
+ # Maglev specific
26
+ def thread_report(index)
27
+ @subject.__gsi_debugger_detailed_report_at(index)
28
+ end
29
+
30
+ def run
31
+ if @subject.__is_continuation
32
+ Thread.start { @subject.__value(nil) }.run
33
+ end
34
+ super
35
+ end
36
+
37
+ def wakeup
38
+ if @subject.__is_continuation
39
+ raise RuntimeError, "cannot wakeup a continuation with #wakeup"
40
+ end
41
+ super
42
+ end
43
+
44
+ def step(symbol = :over)
45
+ case symbol
46
+ when :into
47
+ @subject.__step_over_in_frame(0)
48
+ when :over
49
+ @subject.__step_over_in_frame(1)
50
+ when :through
51
+ raise NotImplementedError, "not implemented yet"
52
+ when Fixnum
53
+ @subject.__step_over_in_frame(symbol)
54
+ end
55
+ end
56
+
57
+ def handle_exception(e = Exception, &block)
58
+ ExceptionHandlers[@subject.object_id] ||= []
59
+ ExceptionHandlers[@subject.object_id] << proc do |ex|
60
+ block[ex] if [*e].any? {|ec| ex.is_a? ec }
61
+ end
62
+
63
+ Exception.install_debug_block do |ex|
64
+ if handlers = ExceptionHandlers[Thread.current.object_id]
65
+ handlers.each {|h| h[ex] }
66
+ end
67
+ end
68
+ end
69
+
70
+ # Maglev specific... for now
71
+ def raw_stack
72
+ stack # Force cache refresh
73
+ end
74
+
75
+ def thread_data
76
+ @subject.__client_data
77
+ end
78
+
79
+ def compiler_state
80
+ thread_data.first
81
+ end
82
+
83
+ def shift(block = Proc.new)
84
+ cm = self.method(:reset).__st_gsmeth
85
+ markLevel = nil
86
+ level = 1
87
+ idx = nil
88
+ while aFrame = Thread.__frame_contents_at(level) and idx == nil
89
+ idx = level if aFrame[0] == cm
90
+ level += 1
91
+ end
92
+ raise(RuntimeError, "no enclosing #reset") if idx.nil?
93
+ # from my caller to the reset caller
94
+ partial_cc = Thread.__partialContinuationFromLevel_to(2, idx + 1)
95
+ res = block.call(reflection.reflect(partial_cc))
96
+
97
+ # Now, return execution to the reset: call and replace the
98
+ # top-of-stack with the result of the block
99
+
100
+ # from reset to reset caller
101
+ cc = Thread.__partialContinuationFromLevel_to(idx - 1, idx + 1)
102
+ Thread.__installPartialContinuation_atLevel_value(cc, idx + 1, res)
103
+ end
104
+
105
+ def reset(block = Proc.new)
106
+ (proc { block.call }).call
107
+ end
108
+
109
+ def call(arg)
110
+ if @subject.__is_partial_continuation
111
+ Thread.__installPartialContinuation_atLevel_value(@subject, 1, arg)
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end