Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Generate & concatenate dtrace hooks.
Browse files Browse the repository at this point in the history
This removes the need to manually escape every newline when defining hook macros
for DTrace/Systemtap. This in turn makes them quite a bit easier to read.

Using this setup is quite simple: dump a header file in vm/dtrace/hooks (using
.h as the extension) and it will be concatenated into vm/dtrace/hooks.h. That
header is in turn included into vm/dtrace/dtrace.h.

This commit also moves the dummy METHOD_HOOK macro into probes_dummy.h. There's
no particular reason to keep it in dtrace.h.
Yorick Peterse committed Nov 6, 2014
1 parent b92254d commit 436005a
Showing 7 changed files with 109 additions and 42 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -88,6 +88,7 @@ web/doc/*/*.new

# Ignore generated DTrace header
vm/dtrace/probes.h
vm/dtrace/hooks.h

# Ignore rubygems except bundled ones
vendor/cache/*
35 changes: 35 additions & 0 deletions rakelib/dtrace_header_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# C header file generated that automatically escaped newlines. This is meant to
# process header files containing DTrace related macros, removing the need to
# manually escape every newline in said files.
class DtraceHeaderGenerator
def initialize(target)
@target = target
end

# Processes the given header files and saves the resulting header as the file
# specified in @target.
def generate(headers)
contents = ''

headers.each do |header_file|
File.open(header_file, 'r') do |handle|
handle.each_line do |line|
contents << "#{line.chomp} \\\n"
end
end

contents << "\n"
end

File.open(@target, 'w') do |handle|
handle.write <<-EOF.strip
#ifndef RUBINIUS_DTRACE_HOOKS_H
#define RUBINIUS_DTRACE_HOOKS_H
#{contents}
#endif
EOF
end
end
end
14 changes: 14 additions & 0 deletions rakelib/vm.rake
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'rakelib/instruction_parser'
require 'rakelib/dtrace_header_generator'
require 'rakelib/generator_task'
require 'rakelib/release'

@@ -51,11 +52,14 @@ TYPE_GEN = %w[ vm/gen/includes.hpp
GENERATED = %W[ vm/gen/config_variables.h
vm/gen/signature.h
vm/dtrace/probes.h
vm/dtrace/hooks.h
#{encoding_database}
#{transcoders_database}
#{vm_release_h}
] + TYPE_GEN + INSN_GEN

DTRACE_HOOKS = FileList.new('vm/dtrace/hooks/*.h')

# Files are in order based on dependencies. For example,
# CompactLookupTable inherits from Tuple, so the header
# for compactlookuptable.hpp has to come after tuple.hpp
@@ -223,6 +227,16 @@ file 'vm/dtrace/probes.h' do |t|
end
end

file 'vm/dtrace/hooks.h' => DTRACE_HOOKS do |t|
if Rubinius::BUILD_CONFIG[:dtrace]
puts "GEN #{t.name}"

generator = DtraceHeaderGenerator.new(t.name)

generator.generate(t.prerequisites)
end
end

if jobs = ENV['JOBS']
@parallel_jobs = jobs.to_i
if @parallel_jobs < 1
46 changes: 4 additions & 42 deletions vm/dtrace/dtrace.h
Original file line number Diff line number Diff line change
@@ -2,52 +2,14 @@
#define RUBINIUS_DTRACE_H

#ifdef HAVE_DTRACE
#include "dtrace/probes.h"

#define RUBINIUS_METHOD_HOOK(probe, state, mod, method, previous) \
{ \
if(RUBINIUS_METHOD_##probe##_ENABLED()) { \
RBX_DTRACE_CONST char* module_name = \
const_cast<RBX_DTRACE_CONST char*>(mod->debug_str(state).c_str()); \
RBX_DTRACE_CONST char* code_name = \
const_cast<RBX_DTRACE_CONST char*>(method->debug_str(state).c_str()); \
RBX_DTRACE_CONST char* file_name = \
const_cast<RBX_DTRACE_CONST char*>("<unknown>"); \
int line = 0; \
if(previous) { \
Symbol* file = previous->file(state); \
if(!file->nil_p()) { \
file_name = const_cast<RBX_DTRACE_CONST char*>(file->debug_str(state).c_str()); \
} \
line = previous->line(state); \
} \
RUBINIUS_METHOD_##probe(module_name, code_name, file_name, line); \
} \
} \

#define RUBINIUS_OBJECT_ALLOCATE_HOOK(state, obj, frame) \
{ \
if(RUBINIUS_OBJECT_ALLOCATE_ENABLED()) { \
Class* mod = obj->direct_class(state); \
RBX_DTRACE_CONST char* module_name = \
const_cast<RBX_DTRACE_CONST char*>(mod->debug_str(state).c_str()); \
RBX_DTRACE_CONST char* file_name = \
const_cast<RBX_DTRACE_CONST char *>("<unknown>"); \
int line = 0; \
if(frame) { \
Symbol* file = frame->file(state); \
if(!file->nil_p()) { \
file_name = const_cast<RBX_DTRACE_CONST char*>(file->debug_str(state).c_str()); \
} \
line = frame->line(state); \
} \
RUBINIUS_OBJECT_ALLOCATE(module_name, file_name, line); \
} \
} \
#include "dtrace/probes.h"
#include "dtrace/hooks.h"

#else

#include "dtrace/probes_dummy.h"
#define RUBINIUS_METHOD_HOOK(probe, state, mod, method, previous) do { } while(0)

#endif

#define RUBINIUS_METHOD_ENTRY_HOOK(state, module, method, previous) \
27 changes: 27 additions & 0 deletions vm/dtrace/hooks/method_hook.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#define RUBINIUS_METHOD_HOOK(probe, state, mod, method, previous)
{
if(RUBINIUS_METHOD_##probe##_ENABLED()) {
RBX_DTRACE_CONST char* module_name =
const_cast<RBX_DTRACE_CONST char*>(mod->debug_str(state).c_str());

RBX_DTRACE_CONST char* code_name =
const_cast<RBX_DTRACE_CONST char*>(method->debug_str(state).c_str());

RBX_DTRACE_CONST char* file_name =
const_cast<RBX_DTRACE_CONST char*>("<unknown>");

int line = 0;

if(previous) {
Symbol* file = previous->file(state);

if(!file->nil_p()) {
file_name = const_cast<RBX_DTRACE_CONST char*>(file->debug_str(state).c_str());
}

line = previous->line(state);
}

RUBINIUS_METHOD_##probe(module_name, code_name, file_name, line);
}
}
26 changes: 26 additions & 0 deletions vm/dtrace/hooks/object_allocate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#define RUBINIUS_OBJECT_ALLOCATE_HOOK(state, obj, frame)
{
if(RUBINIUS_OBJECT_ALLOCATE_ENABLED()) {
Class* mod = obj->direct_class(state);

RBX_DTRACE_CONST char* module_name =
const_cast<RBX_DTRACE_CONST char*>(mod->debug_str(state).c_str());

RBX_DTRACE_CONST char* file_name =
const_cast<RBX_DTRACE_CONST char *>("<unknown>");

int line = 0;

if(frame) {
Symbol* file = frame->file(state);

if(!file->nil_p()) {
file_name = const_cast<RBX_DTRACE_CONST char*>(file->debug_str(state).c_str());
}

line = frame->line(state);
}

RUBINIUS_OBJECT_ALLOCATE(module_name, file_name, line);
}
}
2 changes: 2 additions & 0 deletions vm/dtrace/probes_dummy.h
Original file line number Diff line number Diff line change
@@ -5,6 +5,8 @@
extern "C" {
#endif

#define RUBINIUS_METHOD_HOOK(probe, state, mod, method, previous) do { } while(0)

#define RUBINIUS_METHOD_ENTRY_ENABLED() 0
#define RUBINIUS_METHOD_ENTRY(arg0, arg1, arg2, arg3) do { } while(0)

0 comments on commit 436005a

Please sign in to comment.