Frame.java

  1. /***** BEGIN LICENSE BLOCK *****
  2.  * Version: EPL 1.0/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Eclipse Public
  5.  * License Version 1.0 (the "License"); you may not use this file
  6.  * except in compliance with the License. You may obtain a copy of
  7.  * the License at http://www.eclipse.org/legal/epl-v10.html
  8.  *
  9.  * Software distributed under the License is distributed on an "AS
  10.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  11.  * implied. See the License for the specific language governing
  12.  * rights and limitations under the License.
  13.  *
  14.  * Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
  15.  * Copyright (C) 2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
  16.  * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
  17.  * Copyright (C) 2004-2007 Thomas E Enebo <enebo@acm.org>
  18.  * Copyright (C) 2006 Charles O Nutter <headius@headius.com>
  19.  * Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com>
  20.  *
  21.  * Alternatively, the contents of this file may be used under the terms of
  22.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  23.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  24.  * in which case the provisions of the GPL or the LGPL are applicable instead
  25.  * of those above. If you wish to allow use of your version of this file only
  26.  * under the terms of either the GPL or the LGPL, and not to allow others to
  27.  * use your version of this file under the terms of the EPL, indicate your
  28.  * decision by deleting the provisions above and replace them with the notice
  29.  * and other provisions required by the GPL or the LGPL. If you do not delete
  30.  * the provisions above, a recipient may use your version of this file under
  31.  * the terms of any one of the EPL, the GPL or the LGPL.
  32.  ***** END LICENSE BLOCK *****/
  33. package org.jruby.runtime;

  34. import org.jruby.RubyModule;
  35. import org.jruby.runtime.builtin.IRubyObject;

  36. /**
  37.  * A Frame holds per-call information that needs to persist outside the
  38.  * execution of a given method. Currently a frame holds the following:
  39.  * <ul>
  40.  * <li>The class against which this method is being invoked. This is usually
  41.  * (always?) the class of "self" within this call.</li>
  42.  * <li>The current "self" for the call.</li>
  43.  * <li>The name of the method being invoked during this frame, used for
  44.  * backtraces and "super" invocations.</li>
  45.  * <li>The block passed to this invocation. If the given code body can't
  46.  * accept a block, it will be Block.NULL_BLOCK.</li>
  47.  * <li>Whether this is the frame used for a binding-related call like eval. This
  48.  * is used to determine where to terminate evaled code's backtrace.</li>
  49.  * <li>The current visibility for methods defined during this call. Starts out
  50.  * as PUBLIC by default (in most cases) and can be modified by appropriate
  51.  * Kernel.public/private/protected calls.</li>
  52.  * <li>The jump target marker for non-local returns.</li>
  53.  * </ul>
  54.  * Frames are allocated for all Ruby methods (in compatibility mode, default)
  55.  * and for some core methods. In general, a frame is required for a method to
  56.  * show up in a backtrace, and so some methods only use frame for backtrace
  57.  * information (so-called "backtrace frames").
  58.  *
  59.  * @see ThreadContext
  60.  */
  61. public final class Frame {
  62.     /** The class against which this call is executing. */
  63.     private RubyModule klazz;
  64.    
  65.     /** The 'self' for this frame. */
  66.     private IRubyObject self;
  67.    
  68.     /** The name of the method being invoked in this frame. */
  69.     private String name;

  70.     /**
  71.      * The block that was passed in for this frame (as either a block or a &amp;block argument).
  72.      * The frame captures the block for super/zsuper, but also for Proc.new (with no arguments)
  73.      * and also for block_given?.  Both of those methods needs access to the block of the
  74.      * previous frame to work.
  75.      */
  76.     private Block block = Block.NULL_BLOCK;

  77.     /** The current visibility for anything defined under this frame */
  78.     private Visibility visibility = Visibility.PUBLIC;
  79.    
  80.     /** backref **/
  81.     private IRubyObject backRef;
  82.    
  83.     /** lastline **/
  84.     private IRubyObject lastLine;
  85.    
  86.     /** whether this frame has been captured into a binding **/
  87.     private boolean captured;
  88.    
  89.     /**
  90.      * Empty constructor, since Frame objects are pre-allocated and updated
  91.      * when needed.
  92.      */
  93.     public Frame() {
  94.     }
  95.    
  96.     /**
  97.      * Copy constructor, since Frame objects are pre-allocated and updated
  98.      * when needed.
  99.      */
  100.     private Frame(Frame frame) {
  101.         assert frame.block != null : "Block uses null object pattern.  It should NEVER be null";

  102.         this.self = frame.self;
  103.         this.name = frame.name;
  104.         this.klazz = frame.klazz;
  105.         this.block = frame.block;
  106.         this.visibility = frame.visibility;
  107.     }

  108.     /**
  109.      * Update the frame with just filename and line, used for top-level frames
  110.      * and method.
  111.      */
  112.     public void updateFrame() {
  113.         updateFrame(null, null, null, Block.NULL_BLOCK, 0);
  114.     }

  115.     /**
  116.      * Update the frame with caller information and method name, so it will
  117.      * show up correctly in call stacks.
  118.      *
  119.      * @param name The name of the method being called
  120.      */
  121.     public void updateFrame(String name) {
  122.         this.name = name;
  123.     }

  124.     /**
  125.      * Update the frame based on information from another frame. Used for
  126.      * cloning frames (for blocks, usually) and when entering class bodies.
  127.      *
  128.      * @param frame The frame whose data to duplicate in this frame
  129.      */
  130.     public void updateFrame(Frame frame) {
  131.         assert frame.block != null : "Block uses null object pattern.  It should NEVER be null";

  132.         this.self = frame.self;
  133.         this.name = frame.name;
  134.         this.klazz = frame.klazz;
  135.         this.block = frame.block;
  136.         this.visibility = frame.visibility;
  137.     }

  138.     /**
  139.      * Update the frame based on the given values.
  140.      *
  141.      * @param klazz The class against which the method is being called
  142.      * @param self The 'self' for the method
  143.      * @param name The name under which the method is being invoked
  144.      * @param block The block passed to the method
  145.      * @param jumpTarget The target for non-local jumps (return in block)
  146.      */
  147.     public void updateFrame(RubyModule klazz, IRubyObject self, String name,
  148.                  Block block, int jumpTarget) {
  149.         assert block != null : "Block uses null object pattern.  It should NEVER be null";

  150.         this.self = self;
  151.         this.name = name;
  152.         this.klazz = klazz;
  153.         this.block = block;
  154.         this.visibility = Visibility.PUBLIC;
  155.     }

  156.     /**
  157.      * Update the frame based on the given values.
  158.      *
  159.      * @param self The 'self' for the method
  160.      * @param jumpTarget The target for non-local jumps (return in block)
  161.      */
  162.     public void updateFrameForEval(IRubyObject self, int jumpTarget) {
  163.         this.self = self;
  164.         this.name = null;
  165.         this.visibility = Visibility.PRIVATE;
  166.     }

  167.     /**
  168.      * Clear the frame, as when the call completes. Clearing prevents cached
  169.      * frames from holding references after the call is done.
  170.      */
  171.     public Frame clear() {
  172.         this.self = null;
  173.         this.klazz = null;
  174.         this.block = Block.NULL_BLOCK;
  175.         this.backRef = null;
  176.         this.lastLine = null;
  177.        
  178.         return this;
  179.     }
  180.    
  181.     /**
  182.      * Clone this frame.
  183.      *
  184.      * @return A new frame with duplicate information to the target frame
  185.      */
  186.     public Frame duplicate() {
  187.         return new Frame(this);
  188.     }

  189.     /**
  190.      * Clone this frame for use in backtraces only (avoiding long-lived
  191.      * references to other elements.
  192.      *
  193.      * @return A new frame with identical backtrace information to this frame
  194.      */
  195.     public Frame duplicateForBacktrace() {
  196.         Frame backtraceFrame = new Frame();
  197.         backtraceFrame.name = name;
  198.         return backtraceFrame;
  199.     }

  200.     /**
  201.      * Return class that we are calling against
  202.      *
  203.      * @return The class we are calling against
  204.      */
  205.     public RubyModule getKlazz() {
  206.         return klazz;
  207.     }

  208.     /**
  209.      * Set the class we are calling against.
  210.      *
  211.      * @param klazz the new class
  212.      */
  213.     public void setKlazz(RubyModule klazz) {
  214.         this.klazz = klazz;
  215.     }

  216.     /**
  217.      * Set the method name associated with this frame
  218.      *
  219.      * @param name the new name
  220.      */
  221.     public void setName(String name) {
  222.         this.name = name;
  223.     }

  224.     /**
  225.      * Get the method name associated with this frame
  226.      *
  227.      * @return the method name
  228.      */
  229.     public String getName() {
  230.         return name;
  231.     }

  232.     /**
  233.      * Get the self associated with this frame
  234.      *
  235.      * @return The self for the frame
  236.      */
  237.     public IRubyObject getSelf() {
  238.         return self;
  239.     }

  240.     /**
  241.      * Set the self associated with this frame
  242.      *
  243.      * @param self The new value of self
  244.      */
  245.     public void setSelf(IRubyObject self) {
  246.         this.self = self;
  247.     }
  248.    
  249.     /**
  250.      * Get the visibility at the time of this frame
  251.      *
  252.      * @return The visibility
  253.      */
  254.     public Visibility getVisibility() {
  255.         return visibility;
  256.     }
  257.    
  258.     /**
  259.      * Change the visibility associated with this frame
  260.      *
  261.      * @param visibility The new visibility
  262.      */
  263.     public void setVisibility(Visibility visibility) {
  264.         this.visibility = visibility;
  265.     }
  266.    
  267.     /**
  268.      * Retrieve the block associated with this frame.
  269.      *
  270.      * @return The block of this frame or NULL_BLOCK if no block given
  271.      */
  272.     public Block getBlock() {
  273.         return block;
  274.     }
  275.    
  276.     public IRubyObject getBackRef(IRubyObject nil) {
  277.         IRubyObject backRef = this.backRef;
  278.         return backRef == null ? nil : backRef;
  279.     }
  280.    
  281.     public IRubyObject setBackRef(IRubyObject backRef) {
  282.         return this.backRef = backRef;
  283.     }
  284.    
  285.     public IRubyObject getLastLine(IRubyObject nil) {
  286.         IRubyObject lastLine = this.lastLine;
  287.         return lastLine == null ? nil : lastLine;
  288.     }
  289.    
  290.     public IRubyObject setLastLine(IRubyObject lastLine) {
  291.         return this.lastLine = lastLine;
  292.     }
  293.    
  294.     public void setCaptured(boolean captured) {
  295.         this.captured = captured;
  296.     }
  297.    
  298.     public Frame capture() {
  299.         captured = true;
  300.         return this;
  301.     }
  302.    
  303.     public boolean isCaptured() {
  304.         return captured;
  305.     }

  306.     /* (non-Javadoc)
  307.      * @see java.lang.Object#toString()
  308.      */
  309.     @Override
  310.     public String toString() {
  311.         StringBuilder sb = new StringBuilder(50);
  312.        
  313.         sb.append(klazz);
  314.         if (name != null) sb.append(" in ").append(name);

  315.         return sb.toString();
  316.     }
  317. }