Class: YTLJit::CodeSpace
- Defined in:
- lib/ytljit/marshal.rb,
lib/ytljit/codespace.rb,
ext/ytljit.c
Direct Known Subclasses
Constant Summary collapse
- @@disasm_cache =
{}
- @@disasmed_codespace =
{}
Instance Attribute Summary collapse
-
#disasm_cache ⇒ Object
readonly
Returns the value of attribute disasm_cache.
-
#refer_operands ⇒ Object
readonly
Returns the value of attribute refer_operands.
Class Method Summary collapse
Instance Method Summary collapse
- #[](offset) ⇒ Object
- #[]=(offset, src) ⇒ Object
- #_dump_data ⇒ Object
- #_load_data(obj) ⇒ Object
- #base_address ⇒ Object
- #call(*args) ⇒ Object
- #code ⇒ Object
- #current_pos ⇒ Object
- #current_pos=(val) ⇒ Object
- #disassemble ⇒ Object
- #emit(code) ⇒ Object
- #fill_disasm_cache ⇒ Object
-
#initialize ⇒ CodeSpace
constructor
A new instance of CodeSpace.
- #reset ⇒ Object
- #to_s ⇒ Object
- #update_refer ⇒ Object
- #var_base_address(offset = 0) ⇒ Object
- #var_base_immidiate_address(offset = 0) ⇒ Object
Constructor Details
#initialize ⇒ CodeSpace
Returns a new instance of CodeSpace.
9 10 11 12 |
# File 'lib/ytljit/codespace.rb', line 9 def initialize @refer_operands = [] reset end |
Instance Attribute Details
#disasm_cache ⇒ Object (readonly)
Returns the value of attribute disasm_cache.
14 15 16 |
# File 'lib/ytljit/codespace.rb', line 14 def disasm_cache @disasm_cache end |
#refer_operands ⇒ Object (readonly)
Returns the value of attribute refer_operands.
15 16 17 |
# File 'lib/ytljit/codespace.rb', line 15 def refer_operands @refer_operands end |
Class Method Details
.disasm_cache ⇒ Object
5 6 7 |
# File 'lib/ytljit/codespace.rb', line 5 def self.disasm_cache @@disasm_cache end |
Instance Method Details
#[](offset) ⇒ Object
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'ext/ytljit.c', line 281
VALUE
ytl_code_space_ref(VALUE self, VALUE offset)
{
struct CodeSpace *raw_cs;
int raw_offset;
size_t cooked_offset;
raw_cs = (struct CodeSpace *)DATA_PTR(self);
raw_offset = FIX2INT(offset);
cooked_offset = raw_offset;
if (raw_offset < 0) {
size_t rev_offset = -raw_offset;
cooked_offset = raw_cs->used + rev_offset + 1;
}
return INT2FIX(raw_cs->body[cooked_offset]);
}
|
#[]=(offset, src) ⇒ Object
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'ext/ytljit.c', line 241
VALUE
ytl_code_space_emit(VALUE self, VALUE offset, VALUE src)
{
struct CodeSpace *raw_cs;
char *src_ptr;
size_t src_len;
int raw_offset;
size_t cooked_offset;
struct RData *data_cs;
raw_cs = (struct CodeSpace *)DATA_PTR(self);
src_ptr = RSTRING_PTR(src);
src_len = RSTRING_LEN(src);
raw_offset = FIX2INT(offset);
cooked_offset = raw_offset;
if (raw_offset < 0) {
cooked_offset = raw_cs->used - raw_offset + 1;
}
while (raw_cs->size <= src_len + cooked_offset + 4) {
size_t newsize = (raw_cs->size + sizeof(struct CodeSpace)) * 2;
void *new_cs = csalloc(newsize);
//*(struct CodeSpace *)new_cs = *(struct CodeSpace *)raw_cs;
//memcpy(new_cs, raw_cs, newsize / 2);
csfree(raw_cs);
raw_cs = new_cs;
raw_cs->size = newsize - sizeof(struct CodeSpace);
}
memcpy(raw_cs->body + cooked_offset, src_ptr, src_len);
if (raw_cs->used < cooked_offset + src_len) {
raw_cs->used = cooked_offset + src_len;
}
data_cs = (struct RData *)self;
data_cs->data = raw_cs;
return src;
}
|
#_dump_data ⇒ Object
122 123 124 |
# File 'lib/ytljit/marshal.rb', line 122 def _dump_data [@refer_operands, current_pos, code] end |
#_load_data(obj) ⇒ Object
126 127 128 129 130 131 |
# File 'lib/ytljit/marshal.rb', line 126 def _load_data(obj) self[0] = obj.pop current_pos = obj.pop @org_base_address = base_address @refer_operands = obj.pop end |
#base_address ⇒ Object
319 320 321 322 323 324 325 326 |
# File 'ext/ytljit.c', line 319
VALUE
ytl_code_base_address(VALUE self)
{
struct CodeSpace *raw_cs;
raw_cs = (struct CodeSpace *)DATA_PTR(self);
return ULONG2NUM((unsigned long)raw_cs->body);
}
|
#call(*args) ⇒ Object
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
# File 'ext/ytljit.c', line 328
VALUE
ytl_code_call(int argc, VALUE *argv, VALUE self)
{
VALUE addr;
VALUE args;
VALUE rc;
void *raddr;
rb_scan_args(argc, argv, "11", &addr, &args);
raddr = (void *)NUM2ULONG(addr);
#ifdef __x86_64__
asm("push %%rbx;"
"push %%rdi;"
"push %%rsi;"
"push %%r12;"
"push %%r13;"
"push %%r14;"
"push %%r15;"
"mov %1, %%rax;"
"call *%2;"
"mov %%rax, %0;"
"pop %%r15;"
"pop %%r14;"
"pop %%r13;"
"pop %%r12;"
"pop %%rsi;"
"pop %%rdi;"
"pop %%rbx;"
: "=r"(rc)
: "r"(args), "r"(raddr)
: "%rax", "%rbx");
#elif __CYGWIN__
asm("mov %1, %%eax;"
"call *%2;"
"mov %%eax, %0;"
: "=r"(rc)
: "r"(args), "r"(raddr)
: "%eax", "%ebx");
#elif __i386__
/* push %ebx ? */
asm("mov %1, %%eax;"
"call *%2;"
"mov %%eax, %0;"
: "=r"(rc)
: "r"(args), "r"(raddr)
: "%eax");
/* pop %ebx ? */
#else
#error "only i386 or x86-64 is supported"
#endif
return rc;
}
|
#code ⇒ Object
383 384 385 386 387 388 389 390 391 |
# File 'ext/ytljit.c', line 383
VALUE
ytl_code_space_code(VALUE self)
{
struct CodeSpace *raw_cs;
raw_cs = (struct CodeSpace *)DATA_PTR(self);
return rb_str_new(raw_cs->body, raw_cs->used);
}
|
#current_pos ⇒ Object
300 301 302 303 304 305 306 307 |
# File 'ext/ytljit.c', line 300
VALUE
ytl_code_current_pos(VALUE self)
{
struct CodeSpace *raw_cs;
raw_cs = (struct CodeSpace *)DATA_PTR(self);
return INT2NUM(raw_cs->used);
}
|
#current_pos=(val) ⇒ Object
309 310 311 312 313 314 315 316 317 |
# File 'ext/ytljit.c', line 309
VALUE
ytl_code_set_current_pos(VALUE self, VALUE val)
{
struct CodeSpace *raw_cs;
raw_cs = (struct CodeSpace *)DATA_PTR(self);
raw_cs->used = NUM2INT(val);
return val;
}
|
#disassemble ⇒ Object
90 91 92 93 94 95 |
# File 'lib/ytljit/codespace.rb', line 90 def disassemble fill_disasm_cache @@disasm_cache.each do |add, asm| print "#{add}: #{asm}\n" end end |
#emit(code) ⇒ Object
22 23 24 |
# File 'lib/ytljit/codespace.rb', line 22 def emit(code) self[self.current_pos] = code end |
#fill_disasm_cache ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/ytljit/codespace.rb', line 52 def fill_disasm_cache if @@disasmed_codespace[self] then return end @@disasmed_codespace[self] = true tmpfp = Tempfile.open("ytljitcode") tmpfp.write code tmpfp.close(false) # quick dirty hack to work on Cygwin & Mac OS X/Core2Duo # TODO: bdf and instruction set architecture should be automatically selected case $ruby_platform when /x86_64-darwin/ objcopy_cmd = "gobjcopy -I binary -O mach-o-i386 -B i386 --adjust-vma=#{base_address} #{tmpfp.path}" objdump_cmd = "gobjdump -M x86-64 -D #{tmpfp.path}" when /x86_64/ objcopy_cmd = "objcopy -I binary -O elf64-x86-64 -B i386 --adjust-vma=#{base_address} #{tmpfp.path}" objdump_cmd = "objdump -M x86-64 -D #{tmpfp.path}" when /i.86/ objcopy_cmd = "objcopy -I binary -O elf32-i386 -B i386 --adjust-vma=#{base_address} #{tmpfp.path}" objdump_cmd = "objdump -M i386 -D #{tmpfp.path}" end system(objcopy_cmd) File.popen(objdump_cmd, "r") {|fp| fp.readlines.each do |lin| if /([0-9a-f]*):(\t[0-9a-f ]+? *\t.*)/ =~ lin then src = $2 addr = $1 $symbol_table.each do |val, sym| src.gsub!(val.to_s(16), "#{sym} (#{val})") end @@disasm_cache[addr] = src end end } end |
#reset ⇒ Object
17 18 19 20 |
# File 'lib/ytljit/codespace.rb', line 17 def reset @org_base_address = base_address self.current_pos = 0 end |
#to_s ⇒ Object
393 394 395 396 397 398 399 400 401 |
# File 'ext/ytljit.c', line 393
VALUE
ytl_code_space_to_s(VALUE self)
{
struct CodeSpace *raw_cs;
raw_cs = (struct CodeSpace *)DATA_PTR(self);
return rb_sprintf("#<codeSpace %p base=%p:...>", (void *)self, (void *)raw_cs->body);
}
|
#update_refer ⇒ Object
44 45 46 47 48 49 50 |
# File 'lib/ytljit/codespace.rb', line 44 def update_refer @refer_operands.each do |refop| refop.refer.each do |stfn| stfn.call end end end |
#var_base_address(offset = 0) ⇒ Object
26 27 28 29 30 31 32 33 |
# File 'lib/ytljit/codespace.rb', line 26 def var_base_address(offset = 0) func = lambda { base_address + offset } ovi32 = OpVarMemAddress.new(func) @refer_operands.push ovi32 ovi32 end |
#var_base_immidiate_address(offset = 0) ⇒ Object
35 36 37 38 39 40 41 42 |
# File 'lib/ytljit/codespace.rb', line 35 def var_base_immidiate_address(offset = 0) func = lambda { base_address + offset } ovi32 = OpVarImmidiateAddress.new(func) @refer_operands.push ovi32 ovi32 end |