Class: Rubinius::ToolSets.current::ToolSet::Generator

Inherits:
Object
  • Object
show all
Includes:
GeneratorMethods
Defined in:
lib/rubinius/compiler/generator.rb

Defined Under Namespace

Classes: BasicBlock, Label

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from GeneratorMethods

#add_scope, #allow_private, #call_custom, #cast_array, #cast_for_multi_block_arg, #cast_for_single_block_arg, #cast_for_splat_block_arg, #cast_multi_value, #check_frozen, #check_interrupts, #check_serial, #check_serial_private, #clear_exception, #create_block, #dup_many, #dup_top, #emit_push_literal, #ensure_return, #find_const_fast, #goto, #goto_if_false, #goto_if_true, #instance_of, #invoke_primitive, #is_nil, #kind_of, #make_array, #meta_push_0, #meta_push_1, #meta_push_2, #meta_push_neg_1, #meta_send_call, #meta_send_op_equal, #meta_send_op_gt, #meta_send_op_lt, #meta_send_op_minus, #meta_send_op_plus, #meta_send_op_tequal, #move_down, #noop, #passed_arg, #passed_blockarg, #pop, #pop_many, #pop_unwind, #push_block, #push_block_arg, #push_const_fast, #push_cpath_top, #push_current_exception, #push_exception_state, #push_false, #push_has_block, #push_int, #push_ivar, #push_local_depth, #push_mirror, #push_my_field, #push_my_offset, #push_nil, #push_proc, #push_rubinius, #push_scope, #push_self, #push_stack_local, #push_true, #push_type, #push_undef, #push_variables, #raise_break, #raise_exc, #raise_return, #reraise, #restore_exception_state, #ret, #rotate, #send_method, #send_stack, #send_stack_with_block, #send_stack_with_splat, #send_super_stack_with_block, #send_super_stack_with_splat, #set_call_flags, #set_const, #set_const_at, #set_ivar, #set_literal, #set_local_depth, #set_stack_local, #setup_unwind, #shift_array, #store_my_field, #string_append, #string_build, #string_dup, #swap_stack, #yield_debugger, #yield_splat, #yield_stack, #zsuper

Constructor Details

#initializeGenerator

Returns a new instance of Generator.



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
280
281
# File 'lib/rubinius/compiler/generator.rb', line 243

def initialize
  @stream = []
  @literals_map = Hash.new { |h,k| h[k] = add_literal(k) }
  @literals = []
  @ip = 0
  @modstack = []
  @break = nil
  @redo = nil
  @next = nil
  @retry = nil
  @last_line = nil
  @file = nil
  @lines = []
  @primitive = nil
  @instruction = nil
  @for_block = nil
  @for_module_body = nil

  @required_args = 0
  @post_args = 0
  @total_args = 0

  @detected_args = 0
  @detected_locals = 0

  @splat_index = nil
  @local_names = nil
  @block_index = nil
  @local_count = 0

  @state = []
  @generators = []

  @stack_locals = 0

  @enter_block = new_basic_block
  @current_block = @enter_block
  @max_stack = 0
end

Instance Attribute Details

#block_indexObject

Returns the value of attribute block_index.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def block_index
  @block_index
end

#breakObject

Returns the value of attribute break.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def break
  @break
end

#current_blockObject

Returns the value of attribute current_block.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def current_block
  @current_block
end

#detected_argsObject

Returns the value of attribute detected_args.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def detected_args
  @detected_args
end

#detected_localsObject

Returns the value of attribute detected_locals.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def detected_locals
  @detected_locals
end

#fileObject

Returns the value of attribute file.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def file
  @file
end

#for_blockObject

Returns the value of attribute for_block.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def for_block
  @for_block
end

#for_module_bodyObject

Returns the value of attribute for_module_body.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def for_module_body
  @for_module_body
end

#ipObject (readonly)

Returns the value of attribute ip.



283
284
285
# File 'lib/rubinius/compiler/generator.rb', line 283

def ip
  @ip
end

#iseqObject (readonly)

Returns the value of attribute iseq.



283
284
285
# File 'lib/rubinius/compiler/generator.rb', line 283

def iseq
  @iseq
end

#literalsObject (readonly)

Returns the value of attribute literals.



283
284
285
# File 'lib/rubinius/compiler/generator.rb', line 283

def literals
  @literals
end

#local_countObject

Returns the value of attribute local_count.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def local_count
  @local_count
end

#local_namesObject

Returns the value of attribute local_names.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def local_names
  @local_names
end

#nameObject

Returns the value of attribute name.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def name
  @name
end

#nextObject

Returns the value of attribute next.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def next
  @next
end

#post_argsObject

Returns the value of attribute post_args.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def post_args
  @post_args
end

#primitiveObject

Returns the value of attribute primitive.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def primitive
  @primitive
end

#redoObject

Returns the value of attribute redo.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def redo
  @redo
end

#required_argsObject

Returns the value of attribute required_args.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def required_args
  @required_args
end

#retryObject

Returns the value of attribute retry.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def retry
  @retry
end

#splat_indexObject

Returns the value of attribute splat_index.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def splat_index
  @splat_index
end

#streamObject (readonly)

Returns the value of attribute stream.



283
284
285
# File 'lib/rubinius/compiler/generator.rb', line 283

def stream
  @stream
end

#total_argsObject

Returns the value of attribute total_args.



284
285
286
# File 'lib/rubinius/compiler/generator.rb', line 284

def total_args
  @total_args
end

Instance Method Details

#accumulate_stack(size) ⇒ Object



459
460
461
# File 'lib/rubinius/compiler/generator.rb', line 459

def accumulate_stack(size)
  @max_stack = size if size > @max_stack
end

#add_literal(literal) ⇒ Object

Add literal exists to allow RegexLiteral’s to create a new regex literal object at run-time. All other literals should be added via find_literal, which re-use an existing matching literal if one exists.



507
508
509
510
511
# File 'lib/rubinius/compiler/generator.rb', line 507

def add_literal(literal)
  index = @literals.size
  @literals << literal
  return index
end

#closeObject



429
430
431
432
433
434
435
436
# File 'lib/rubinius/compiler/generator.rb', line 429

def close
  if @lines.empty?
    msg = "closing a method definition with no line info: #{file}:#{line}"
    raise Exception, msg
  end

  @lines << @ip
end

#definition_line(line) ⇒ Object



382
383
384
385
386
387
388
389
390
391
# File 'lib/rubinius/compiler/generator.rb', line 382

def definition_line(line)
  unless @stream.empty?
    raise Exception, "only use #definition_line first"
  end

  @lines << -1
  @lines << line

  @last_line = line
end

#encodeObject

Formalizers



298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/rubinius/compiler/generator.rb', line 298

def encode
  @iseq = Rubinius::InstructionSequence.new @stream.to_tuple

  begin
    # Validate the stack and calculate the max depth
    @enter_block.validate_stack
  rescue Exception => e
    if $DEBUG
      puts "Error computing stack for #{@name}: #{e.message} (#{e.class})"
    end
    raise e
  end

  @generators.each { |x| @literals[x].encode }
end

#execute(node) ⇒ Object Also known as: run



290
291
292
# File 'lib/rubinius/compiler/generator.rb', line 290

def execute(node)
  node.bytecode self
end

#find_const(name) ⇒ Object

The find_const instruction itself is unused right now. The instruction parser does not emit a GeneratorMethods#find_const. This method/opcode was used in the compiler before the find_const_fast instruction. Rather than changing the compiler code, this helper was used.



549
550
551
# File 'lib/rubinius/compiler/generator.rb', line 549

def find_const(name)
  find_const_fast find_literal(name)
end

#find_literal(literal) ⇒ Object

Find the index for the specified literal, or create a new slot if the literal has not been encountered previously.



500
501
502
# File 'lib/rubinius/compiler/generator.rb', line 500

def find_literal(literal)
  @literals_map[literal]
end

#ip_to_line(ip) ⇒ Object



416
417
418
419
420
421
422
423
424
425
426
427
# File 'lib/rubinius/compiler/generator.rb', line 416

def ip_to_line(ip)
  total = @lines.size - 2
  i = 0

  while i < total
    if ip >= @lines[i] and ip <= @lines[i+2]
      return @lines[i+1]
    end

    i += 2
  end
end

#last_match(mode, which) ⇒ Object



581
582
583
584
585
# File 'lib/rubinius/compiler/generator.rb', line 581

def last_match(mode, which)
  push_int Integer(mode)
  push_int Integer(which)
  invoke_primitive :regexp_last_match_result, 2
end

#lineObject



412
413
414
# File 'lib/rubinius/compiler/generator.rb', line 412

def line
  @last_line
end

#max_stack_sizeObject



463
464
465
466
467
# File 'lib/rubinius/compiler/generator.rb', line 463

def max_stack_size
  size = @max_stack + @local_count + @stack_locals
  size += 1 if @for_block
  size
end

#meta_to_s(name = :to_s, priv = true) ⇒ Object



641
642
643
644
# File 'lib/rubinius/compiler/generator.rb', line 641

def meta_to_s(name=:to_s, priv=true)
  allow_private if priv
  super find_literal(name)
end

#new_basic_blockObject

Helpers



455
456
457
# File 'lib/rubinius/compiler/generator.rb', line 455

def new_basic_block
  BasicBlock.new self
end

#new_labelObject



442
443
444
# File 'lib/rubinius/compiler/generator.rb', line 442

def new_label
  Label.new(self)
end

#new_stack_localObject



469
470
471
472
473
# File 'lib/rubinius/compiler/generator.rb', line 469

def new_stack_local
  idx = @stack_locals
  @stack_locals += 1
  return idx
end

#package(klass) ⇒ Object



314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/rubinius/compiler/generator.rb', line 314

def package(klass)
  @generators.each { |x| @literals[x] = @literals[x].package klass }

  code = klass.new
  code.iseq           = @iseq
  code.literals       = @literals.to_tuple
  code.lines          = @lines.to_tuple

  code.required_args  = @required_args
  code.post_args      = @post_args
  code.total_args     = @total_args
  code.splat          = @splat_index
  code.block_index    = @block_index
  code.local_count    = @local_count
  code.local_names    = @local_names.to_tuple if @local_names

  code.stack_size     = max_stack_size
  code.file           = @file
  code.name           = @name
  code.primitive      = @primitive

  if @for_block
    code. :for_block, true
  end

  if @for_module_body
    code. :for_module_body, true
  end

  code
end

#pop_modifiersObject



378
379
380
# File 'lib/rubinius/compiler/generator.rb', line 378

def pop_modifiers
  @break, @redo, @next, @retry = @modstack.pop
end

#pop_stateObject



370
371
372
# File 'lib/rubinius/compiler/generator.rb', line 370

def pop_state
  @state.pop
end

#push(what) ⇒ Object



475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
# File 'lib/rubinius/compiler/generator.rb', line 475

def push(what)
  case what
  when :true
    push_true
  when :false
    push_false
  when :self
    push_self
  when :nil
    push_nil
  when Integer
    push_int what
  else
    raise CompileError, "Unknown push argument '#{what.inspect}'"
  end
end

#push_arg(idx) ⇒ Object

Minor meta operations that can be used to detect the number of method arguments needed



571
572
573
574
# File 'lib/rubinius/compiler/generator.rb', line 571

def push_arg(idx)
  push_local(idx)
  @detected_args = @detected_locals
end

#push_const(name) ⇒ Object

The push_const instruction itself is unused right now. The instruction parser does not emit a GeneratorMethods#push_const. This method/opcode was used in the compiler before the push_const_fast instruction. Rather than changing the compiler code, this helper was used.



541
542
543
# File 'lib/rubinius/compiler/generator.rb', line 541

def push_const(name)
  push_const_fast find_literal(name)
end

#push_generator(generator) ⇒ Object



492
493
494
495
496
# File 'lib/rubinius/compiler/generator.rb', line 492

def push_generator(generator)
  index = push_literal generator
  @generators << index
  index
end

#push_literal(literal) ⇒ Object

Pushes the specified literal value into the literal’s tuple



514
515
516
517
518
# File 'lib/rubinius/compiler/generator.rb', line 514

def push_literal(literal)
  index = find_literal literal
  emit_push_literal index
  return index
end

#push_literal_at(index) ⇒ Object

Pushes the literal value on the stack into the specified position in the literals tuple. Most timees, push_literal should be used instead; this method exists to support RegexLiteral, where the compiled literal value (a Regex object) does not exist until runtime.



532
533
534
535
# File 'lib/rubinius/compiler/generator.rb', line 532

def push_literal_at(index)
  emit_push_literal index
  return index
end

#push_local(idx) ⇒ Object



553
554
555
556
557
558
559
# File 'lib/rubinius/compiler/generator.rb', line 553

def push_local(idx)
  if @detected_locals <= idx
    @detected_locals = idx + 1
  end

  super
end

#push_modifiersObject



374
375
376
# File 'lib/rubinius/compiler/generator.rb', line 374

def push_modifiers
  @modstack << [@break, @redo, @next, @retry]
end

#push_state(scope) ⇒ Object



366
367
368
# File 'lib/rubinius/compiler/generator.rb', line 366

def push_state(scope)
  @state << AST::State.new(scope)
end

#push_unique_literal(literal) ⇒ Object

Puts what is the literals tuple without trying to see if something that is like what is already there.



522
523
524
525
526
# File 'lib/rubinius/compiler/generator.rb', line 522

def push_unique_literal(literal)
  index = add_literal literal
  emit_push_literal index
  return index
end

#send(meth, count, priv = false) ⇒ Object



587
588
589
590
591
592
593
594
595
596
597
598
599
# File 'lib/rubinius/compiler/generator.rb', line 587

def send(meth, count, priv=false)
  allow_private if priv

  unless count.kind_of? Fixnum
    raise CompileError, "count must be a number"
  end

  idx = find_literal(meth)

  # Don't use send_method, it's only for when the syntax
  # specified no arguments and no parens.
  send_stack idx, count
end

#send_primitive(name) ⇒ Object



438
439
440
# File 'lib/rubinius/compiler/generator.rb', line 438

def send_primitive(name)
  @primitive = name
end

#send_super(meth, args, splat = false) ⇒ Object



631
632
633
634
635
636
637
638
639
# File 'lib/rubinius/compiler/generator.rb', line 631

def send_super(meth, args, splat=false)
  idx = find_literal(meth)

  if splat
    send_super_stack_with_splat idx, args
  else
    send_super_stack_with_block idx, args
  end
end

#send_vcall(meth) ⇒ Object

Do a private send to self with no arguments specified, ie, a vcall style send.



603
604
605
606
# File 'lib/rubinius/compiler/generator.rb', line 603

def send_vcall(meth)
  idx = find_literal(meth)
  send_method idx
end

#send_with_block(meth, count, priv = false) ⇒ Object



608
609
610
611
612
613
614
615
616
617
618
# File 'lib/rubinius/compiler/generator.rb', line 608

def send_with_block(meth, count, priv=false)
  allow_private if priv

  unless count.kind_of? Fixnum
    raise CompileError, "count must be a number"
  end

  idx = find_literal(meth)

  send_stack_with_block idx, count
end

#send_with_splat(meth, args, priv = false, concat = false) ⇒ Object



620
621
622
623
624
625
626
627
628
629
# File 'lib/rubinius/compiler/generator.rb', line 620

def send_with_splat(meth, args, priv=false, concat=false)
  val = 0
  val |= Rubinius::InstructionSet::CALL_FLAG_CONCAT if concat
  set_call_flags val unless val == 0

  allow_private if priv

  idx = find_literal(meth)
  send_stack_with_splat idx, args
end

#set_arg(idx) ⇒ Object



576
577
578
579
# File 'lib/rubinius/compiler/generator.rb', line 576

def set_arg(idx)
  set_local(idx)
  @detected_args = @detected_locals
end

#set_line(line) ⇒ Object

Raises:

  • (Exception)


393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
# File 'lib/rubinius/compiler/generator.rb', line 393

def set_line(line)
  raise Exception, "source code line cannot be nil" unless line

  if !@last_line
    @lines << @ip
    @lines << line
    @last_line = line
  elsif line != @last_line
    if @lines[-2] == @ip
      @lines[-1] = line
    else
      @lines << @ip
      @lines << line
    end

    @last_line = line
  end
end

#set_local(idx) ⇒ Object



561
562
563
564
565
566
567
# File 'lib/rubinius/compiler/generator.rb', line 561

def set_local(idx)
  if @detected_locals <= idx
    @detected_locals = idx + 1
  end

  super
end

#stateObject

Commands (these don’t generate data in the stream)



362
363
364
# File 'lib/rubinius/compiler/generator.rb', line 362

def state
  @state.last
end

#use_detectedObject



346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'lib/rubinius/compiler/generator.rb', line 346

def use_detected
  if @required_args < @detected_args
    @required_args = @detected_args
  end

  if @total_args < @detected_args
    @total_args = @detected_args
  end

  if @local_count < @detected_locals
    @local_count = @detected_locals
  end
end