rubinius/rubinius

View on GitHub
machine/machine_code.hpp

Summary

Maintainability
Test Coverage
#ifndef RBX_VMMETHOD_HPP
#define RBX_VMMETHOD_HPP

#include "defines.hpp"
#include "call_frame.hpp"
#include "executor.hpp"
#include "memory/root.hpp"
#include "primitives.hpp"
#include "type_info.hpp"
#include "unwind_info.hpp"
#include "memory.hpp"

#include "class/class.hpp"
#include "class/compiled_code.hpp"
#include "memory/code_resource.hpp"

#include <atomic>
#include <stdint.h>

namespace rubinius {
  namespace diagnostics {
    class Measurement;
  }

  typedef uintptr_t opcode;

  class CompiledCode;
  class CallSite;
  class ConstantCache;
  class MachineCode;
  class UnwindSite;

  struct CallFrame;

  typedef Object* (*InterpreterRunner)(STATE, MachineCode* const mcode);

  class MachineCode : public memory::CodeResource {
  public:

    enum Flags {
      eNoInline  = 1 << 0,
      eCompiling = 1 << 1
    };

    enum ExecuteStatus {
      eInterpret,
      eJIT,
      eJITDisable,
    };

    static std::atomic<uint64_t> code_serial;

  public:
    InterpreterRunner run;

    opcode* opcodes;

    size_t total;
    TypeInfo* type;

    bool keywords;

    intptr_t total_args;
    intptr_t required_args;
    intptr_t post_args;
    intptr_t splat_position;
    intptr_t keywords_count;

    intptr_t stack_size;
    intptr_t number_of_locals;

    intptr_t registers;

    intptr_t sample_count;
    intptr_t call_count;
    intptr_t uncommon_count;

    attr_field(call_site_count, size_t);
    attr_field(constant_cache_count, size_t);
    attr_field(references_count, size_t);
    attr_field(references, size_t*);
    attr_field(unwind_site_count, size_t);
    attr_field(serial, uint64_t);
    attr_field(nil_id, uint32_t);

    std::string _name_;
    std::string _location_;

    executor unspecialized;
    executor fallback;

  private:
    ExecuteStatus execute_status_;

  public:
    uint32_t debugging;

  private:
    uint32_t flags; // Used to store bit flags
  public: // Methods
    static uint64_t get_serial() {
      return ++code_serial;
    }

    static void bootstrap(STATE);

    static MachineCode* create(STATE, CompiledCode* code);

    MachineCode(STATE, CompiledCode* code);
    virtual ~MachineCode();
    virtual void cleanup(STATE, memory::CodeManager* code) {}
    virtual int size();

    const std::string& name() const {
      return _name_;
    }

    const std::string& location() const {
      return _location_;
    }

    bool jitted_p() const {
      return execute_status_ == eJIT;
    }

    bool jit_disabled() const {
      return execute_status_ == eJITDisable;
    }

    bool compiling_p() const {
      return (flags & eCompiling) == eCompiling;
    }

    void set_compiling() {
      flags |= eCompiling;
    }

    void clear_compiling() {
      flags &= ~eCompiling;
    }

    void set_execute_status(ExecuteStatus s) {
      execute_status_ = s;
    }

    bool no_inline_p() const {
      return (flags & eNoInline) == eNoInline;
    }

    void set_no_inline() {
      flags |= eNoInline;
    }

    void finalize(STATE);

    CallSite* call_site(STATE, int ip);
    ConstantCache* constant_cache(STATE, int ip);

    Tuple* call_sites(STATE);
    Tuple* constant_caches(STATE);

    void store_call_site(STATE, CompiledCode* code, int ip, CallSite* call_site);
    void store_constant_cache(STATE, CompiledCode* code, int ip, ConstantCache* constant_cache);
    void store_unwind_site(STATE, CompiledCode* code, int ip, UnwindSite* unwind_site);
    void store_measurement(STATE, CompiledCode* code, int ip, diagnostics::Measurement* m);

    void specialize(STATE, CompiledCode* original, TypeInfo* ti);
    static Object* execute(STATE, Executable* exec, Module* mod, Arguments& args);

    template <typename ArgumentHandler>
      static Object* execute_specialized(STATE, Executable* exec, Module* mod, Arguments& args);

    Object* execute_as_script(STATE, CompiledCode* code);

    /**
     *  Interpreting implementation.
     *
     *  @see  machine/instructions.cpp for the code.
     */
    static Object* interpreter(STATE, MachineCode* const mcode);

    static Object* debugger_interpreter(STATE, MachineCode* const mcode);
    static Object* debugger_interpreter_continue(STATE,
                                       MachineCode* const mcode,
                                       CallFrame* const call_frame,
                                       int sp,
                                       InterpreterState& is,
                                       UnwindInfoSet& unwinds);

    static Object* uncommon_interpreter(STATE, MachineCode* const mcode,
      CallFrame* const call_frame, int32_t entry_ip, intptr_t sp,
      CallFrame* const method_call_frame, UnwindInfoSet& unwinds,
      bool force_deoptimization);

    void setup_argument_handler();
  };
};

#endif