Example #1
0
inline bool cast_array(STATE, CallFrame* call_frame) {
    // Use stack_top and not stack_pop because we may need
    // to preserve and reread the value from the stack below.
    Object* t1 = stack_top();
    if(t1->nil_p()) {
        t1 = Array::create(state, 0);
    } else if(Tuple* tup = try_as<Tuple>(t1)) {
        t1 = Array::from_tuple(state, tup);
    } else if(!rubinius::kind_of<Array>(t1)) {
        Object* recv = G(type);
        Arguments args(G(sym_coerce_to_array), recv, 1, &t1);
        Dispatch dispatch(G(sym_coerce_to_array));

        Object* res = dispatch.send(state, args);

        // If the send still doesn't produce an array, wrap
        // the value in one.
        if(res && !rubinius::kind_of<Array>(res)) {
            Array* ary = Array::create(state, 1);
            // Don't read t1 here, it's not GC safe because we called
            // a method.
            ary->set(state, 0, stack_top());
            t1 = ary;
        } else {
            t1 = res;
        }
    }

    (void)stack_pop(); // Remove original value

    CHECK_AND_PUSH(t1);
}
Example #2
0
    inline bool find_const(STATE, CallFrame* call_frame, intptr_t literal) {
      Module* under = as<Module>(stack_pop());

      ConstantCache* cache = reinterpret_cast<ConstantCache*>(literal);

      Object* res = cache->retrieve(state, under, call_frame->lexical_scope());

      if(!res) {
        ConstantMissingReason reason;

        Symbol* sym = cache->name();
        res = Helpers::const_get_under(state, under, sym, &reason);

        if(reason == vFound) {
          OnStack<3> os(state, cache, under, res);
          if(Autoload* autoload = try_as<Autoload>(res)) {
            res = autoload->resolve(state, under);
          }

          if(res) {
            ConstantCache* update = ConstantCache::create(state, cache, res, under, call_frame->lexical_scope());
            cache->update_constant_cache(state, update);
          }
        } else {
          res = Helpers::const_missing_under(state, under, sym);
        }
      }

      CHECK_AND_PUSH(res);
    }
Example #3
0
    inline bool yield_splat(STATE, CallFrame* call_frame, intptr_t count) {
      Object* ary = stack_pop();
      Object* t1 = call_frame->scope->block();

      Arguments args(G(sym_call), t1, count, stack_back_position(count));

      if(!ary->nil_p()) {
        args.append(state, as<Array>(ary));
      }

      if(BlockEnvironment *env = try_as<BlockEnvironment>(t1)) {
        call_frame->return_value = env->call(state, args);
      } else if(Proc* proc = try_as<Proc>(t1)) {
        call_frame->return_value = proc->yield(state, args);
      } else if(t1->nil_p()) {
        state->raise_exception(Exception::make_lje(state));
        call_frame->return_value = NULL;
      } else {
        Dispatch dispatch(G(sym_call));
        call_frame->return_value = dispatch.send(state, args);
      }

      stack_clear(count);

      state->vm()->checkpoint(state);

      CHECK_AND_PUSH(call_frame->return_value);
    }
Example #4
0
    inline bool create_block(STATE, CallFrame* call_frame, intptr_t literal) {
      Object* code_or_id = reinterpret_cast<Object*>(literal);
      CompiledCode* code = 0;

      if(!(code = try_as<CompiledCode>(code_or_id))) {
        code = CodeDB::load(state, as<String>(code_or_id));
        // TODO: instructions
        // store_literal(reinterpret_cast<opcode>(code));
      }

      Object* be = BlockEnvironment::under_call_frame(state, code, call_frame->machine_code);

      CHECK_AND_PUSH(be);
    }
Example #5
0
    inline bool send_stack(STATE, CallFrame* call_frame, intptr_t literal, intptr_t count) {
      Object* recv = stack_back(count);
      CallSite* call_site = reinterpret_cast<CallSite*>(literal);

      Arguments args(call_site->name(), recv, cNil, count,
                     stack_back_position(count));

      stack_clear(count + 1);

      call_frame->return_value = call_site->execute(state, args);

      state->vm()->checkpoint(state);

      CHECK_AND_PUSH(call_frame->return_value);
    }
Example #6
0
    inline bool push_ivar(STATE, CallFrame* call_frame, intptr_t literal) {
      Symbol* sym = reinterpret_cast<Symbol*>(literal);
      Object* ret = call_frame->self()->get_ivar(state, sym);

      CHECK_AND_PUSH(ret);
    }
Example #7
0
    inline bool zsuper(STATE, CallFrame* call_frame, intptr_t literal) {
      Object* block = stack_pop();
      Object* const recv = call_frame->self();

      VariableScope* scope = call_frame->method_scope(state);
      interp_assert(scope);

      MachineCode* mc = scope->method()->machine_code();
      Object* splat_obj = 0;
      Array* splat = 0;

      size_t arg_count = mc->total_args;

      if(mc->splat_position >= 0) {
        splat_obj = scope->get_local(state, mc->splat_position);
        splat = try_as<Array>(splat_obj);
        if(splat) {
          arg_count += splat->size();
        } else {
          arg_count++;
        }
      }

      Tuple* tup = Tuple::create(state, arg_count);
      native_int tup_index = 0;

      native_int fixed_args;
      if(splat) {
        fixed_args = mc->splat_position;
      } else if(mc->keywords) {
        fixed_args = mc->total_args - 1;
      } else {
        fixed_args = mc->total_args;
      }
      for(native_int i = 0; i < fixed_args; i++) {
        tup->put(state, tup_index++, scope->get_local(state, i));
      }

      if(splat) {
        for(native_int i = 0; i < splat->size(); i++) {
          tup->put(state, tup_index++, splat->get(state, i));
        }
      } else if(splat_obj) {
        tup->put(state, tup_index++, splat_obj);
      }

      if(mc->post_args) {
        native_int post_position = mc->splat_position + 1;
        for(native_int i = post_position; i < post_position + mc->post_args; i++) {
          tup->put(state, tup_index++, scope->get_local(state, i));
        }
      }

      if(mc->keywords) {
        native_int placeholder_position = splat_obj ? mc->total_args : mc->total_args - 1;
        native_int keywords_position = placeholder_position + 1;

        Object* placeholder = scope->get_local(state, placeholder_position);
        Array* ary = Array::create(state, 2);

        for(native_int i = keywords_position; i <= mc->keywords_count; i++) {
          ary->set(state, 0, as<Symbol>(call_frame->compiled_code->local_names()->at(state, i)));
          ary->set(state, 1, scope->get_local(state, i));

          placeholder->send(state, state->symbol("[]="), ary);
        }

        tup->put(state, tup_index++, scope->get_local(state, placeholder_position));
      }

      CallSite* call_site = reinterpret_cast<CallSite*>(literal);

      Arguments new_args(call_site->name(), recv, block, arg_count, 0);
      new_args.use_tuple(tup, arg_count);

      Object* ret;

      Symbol* current_name = call_frame->original_name();
      if(call_site->name() != current_name) {
        call_site->name(state, current_name);
      }

      ret = call_site->execute(state, new_args);

      state->vm()->checkpoint(state);

      CHECK_AND_PUSH(ret);
    }