is_a 0.0.3 → 0.1.0

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.
data/README.md CHANGED
@@ -18,6 +18,9 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
+ ### BasicObject
22
+ If you got an object via `_id2ref` or from similar place - do not rush to duck-typing, it may be a BasicObject and not respond to `respond_to?`. IsA aims in handling such cases.
23
+
21
24
  ```ruby
22
25
  require 'is_a'
23
26
 
@@ -39,6 +42,31 @@ ObjectSpace._id2ref(id) == obj # => true
39
42
  #For 1.9.3 use BasicObject#__id__
40
43
  ```
41
44
 
45
+ ### Fast getting of lines from caller
46
+
47
+ Ruby's `caller` is handy, but sometimes you do not need the whole array of strings it allocates generates on each call.
48
+
49
+ `IsA.caller_line` (also global `caller_line`) is a lot faster and does not mess your heap that lot (allocates just the result string, meaning fewer GC):
50
+
51
+ ```ruby
52
+ require 'is_a'
53
+ require 'benchmark'
54
+ n = 10000
55
+ Benchmark.bm(11) do |x|
56
+ x.report("caller[1]") { n.times { caller[1] } }
57
+ x.report("caller_line") { n.times { caller_line(1) } }
58
+ end
59
+ ```
60
+
61
+ Results:
62
+
63
+ ```
64
+ user system total real
65
+ caller[1] 0.430000 0.010000 0.440000 ( 0.443102)
66
+ caller_line 0.010000 0.000000 0.010000 ( 0.002275)
67
+ ```
68
+
69
+
42
70
  ## Contributing
43
71
 
44
72
  1. Fork it
data/Rakefile CHANGED
@@ -58,6 +58,20 @@ task :test => :compile do
58
58
  puts "object? FAIL"
59
59
  end
60
60
 
61
+ def test_caller
62
+ puts "Real caller: #{caller[0]}"
63
+ puts "Caller at 0: #{IsA.caller_line(0)}"
64
+ puts caller_line
65
+ end
66
+
67
+ test_caller
68
+
69
+ require 'benchmark'
70
+ n = 10000
71
+ Benchmark.bm(11) do |x|
72
+ x.report("caller[1]") { n.times { caller[1] } }
73
+ x.report("caller_line") { n.times { caller_line(1) } }
74
+ end
61
75
 
62
76
  #require 'heap_dump'
63
77
  #HeapDump.dump
@@ -1,3 +1,33 @@
1
1
  require 'mkmf'
2
+ require 'debugger/ruby_core_source'
2
3
 
3
- create_makefile('is_a')
4
+ unless ARGV.any? {|arg| arg.include?('--with-ruby-include') }
5
+ require 'rbconfig'
6
+ bindir = RbConfig::CONFIG['bindir']
7
+ if bindir =~ %r{(^.*/\.rbenv/versions)/([^/]+)/bin$}
8
+ ruby_include = "#{$1}/#{$2}/include/ruby-1.9.1/ruby-#{$2}"
9
+ ARGV << "--with-ruby-include=#{ruby_include}"
10
+ elsif bindir =~ %r{(^.*/\.rvm/rubies)/([^/]+)/bin$}
11
+ ruby_include = "#{$1}/#{$2}/include/ruby-1.9.1/#{$2}"
12
+ ruby_include = "#{ENV['rvm_path']}/src/#{$2}" unless File.exist?(ruby_include)
13
+ ARGV << "--with-ruby-include=#{ruby_include}"
14
+ end
15
+ puts "Using ruby source from #{ruby_include}"
16
+ end
17
+
18
+ hdrs = ->{
19
+ res = %w{
20
+ vm_core.h
21
+ }.all?{|hdr| have_header(hdr)}
22
+ res
23
+ }
24
+
25
+ # create_makefile('is_a')
26
+ if !Debugger::RubyCoreSource::create_makefile_with_core(hdrs, "is_a")
27
+ STDERR.print("Makefile creation failed\n")
28
+ STDERR.print("*************************************************************\n\n")
29
+ STDERR.print(" NOTE: If your headers were not found, try passing\n")
30
+ STDERR.print(" --with-ruby-include=PATH_TO_HEADERS \n\n")
31
+ STDERR.print("*************************************************************\n\n")
32
+ exit(1)
33
+ end
@@ -19,8 +19,82 @@ rb_object_id_of(VALUE self, VALUE obj)
19
19
  return rb_obj_id(obj);
20
20
  }
21
21
 
22
+
23
+ #ifdef HAVE_VM_CORE_H
24
+ #include "ruby/encoding.h"
25
+ #include "vm_core.h"
26
+
27
+ #define HAVE_CALLER_AT
28
+ static VALUE caller_line(int offset)
29
+ {
30
+ const rb_thread_t *th = ((rb_thread_t *)RTYPEDDATA_DATA(rb_thread_current()));
31
+ offset += 2;
32
+ if(offset < 0)
33
+ return Qnil;
34
+
35
+ rb_control_frame_t* cfp = th->cfp + offset;
36
+ const rb_control_frame_t* stack_end = (void *)(th->stack + th->stack_size);
37
+
38
+ if(cfp < stack_end){
39
+ if (cfp->iseq != 0) {
40
+ if (cfp->pc != 0) {
41
+ rb_iseq_t *iseq = cfp->iseq;
42
+ int line_no = rb_vm_get_sourceline(cfp);
43
+ VALUE file = iseq->filename,
44
+ name = iseq->name;
45
+ if (line_no) {
46
+ return rb_enc_sprintf(
47
+ rb_enc_compatible(file, name),
48
+ "%s:%d:in `%s'",
49
+ RSTRING_PTR(file), line_no, RSTRING_PTR(name));
50
+ } else {
51
+ return rb_enc_sprintf(
52
+ rb_enc_compatible(file, name),
53
+ "%s:in `%s'",
54
+ RSTRING_PTR(file), RSTRING_PTR(name));
55
+ }
56
+ }
57
+ } else {
58
+ // printf("CFUNC\n");
59
+ return Qnil;
60
+ }
61
+ } else {
62
+ // level is out of bounds
63
+ }
64
+ return Qnil;
65
+ }
66
+
67
+ static VALUE
68
+ rb_caller_line(VALUE self, VALUE r_offset)
69
+ {
70
+ int offset = NUM2INT(r_offset); // we are not interested in self
71
+ return caller_line(offset);
72
+ }
73
+
74
+ static VALUE rb_caller_line_global(int argc, VALUE* argv)
75
+ {
76
+ VALUE level;
77
+ int lev;
78
+
79
+ rb_scan_args(argc, argv, "01", &level);
80
+
81
+ if (NIL_P(level))
82
+ lev = 0;
83
+ else
84
+ lev = NUM2INT(level);
85
+
86
+ if (lev < 0)
87
+ rb_raise(rb_eArgError, "negative level (%d)", lev);
88
+ return caller_line(lev);
89
+ }
90
+ #endif
91
+
22
92
  void Init_is_a(){
23
93
  rb_mIsA = rb_define_module("IsA");
24
94
  rb_define_singleton_method(rb_mIsA, "class_of", rb_get_class_of, 1);
25
95
  rb_define_singleton_method(rb_mIsA, "id_of", rb_object_id_of, 1);
96
+ #ifdef HAVE_CALLER_AT
97
+ rb_define_singleton_method(rb_mIsA, "caller_line", rb_caller_line, 1);
98
+ rb_define_global_function("caller_line", rb_caller_line_global, -1);
99
+ #endif
26
100
  }
@@ -17,5 +17,6 @@ Gem::Specification.new do |gem|
17
17
 
18
18
  gem.extensions = "ext/is_a/extconf.rb"
19
19
 
20
+ gem.add_dependency("debugger-ruby_core_source")
20
21
  gem.add_development_dependency "rake-compiler"
21
22
  end
@@ -1,3 +1,3 @@
1
1
  module IsA
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: is_a
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,27 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-11 00:00:00.000000000Z
12
+ date: 2013-07-02 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: debugger-ruby_core_source
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: rake-compiler
16
- requirement: &70116595563300 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
17
33
  none: false
18
34
  requirements:
19
35
  - - ! '>='
@@ -21,7 +37,12 @@ dependencies:
21
37
  version: '0'
22
38
  type: :development
23
39
  prerelease: false
24
- version_requirements: *70116595563300
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
25
46
  description: Fear weak references to BasicObject no more
26
47
  email:
27
48
  - vasilyfedoseyev@gmail.com
@@ -52,17 +73,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
52
73
  - - ! '>='
53
74
  - !ruby/object:Gem::Version
54
75
  version: '0'
76
+ segments:
77
+ - 0
78
+ hash: 3551024361612674054
55
79
  required_rubygems_version: !ruby/object:Gem::Requirement
56
80
  none: false
57
81
  requirements:
58
82
  - - ! '>='
59
83
  - !ruby/object:Gem::Version
60
84
  version: '0'
85
+ segments:
86
+ - 0
87
+ hash: 3551024361612674054
61
88
  requirements: []
62
89
  rubyforge_project:
63
- rubygems_version: 1.8.15
90
+ rubygems_version: 1.8.24
64
91
  signing_key:
65
92
  specification_version: 3
66
93
  summary: Defines methods to introspect any ruby object more deeply
67
94
  test_files: []
68
- has_rdoc: