Exemple #1
0
 AccessVariable* AccessVariable::allocate(STATE) {
   AccessVariable* av = state->new_object<AccessVariable>(G(access_variable));
   av->inliners_ = 0;
   av->prim_index_ = -1;
   av->set_executor(AccessVariable::access_execute);
   return av;
 }
Exemple #2
0
  /* Run when an AccessVariable is executed. Uses the details in exec
   * to access instance variables of args.recv() */
  Object* AccessVariable::access_execute(STATE, CallFrame* call_frame, Executable* exec, Module* mod,
                                         Arguments& args) {
    AccessVariable* access = as<AccessVariable>(exec);
    Object* const self = args.recv();

    /* The writer case. */
    if(access->write()->true_p()) {
      if(CBOOL(self->frozen_p(state))) {
        Exception::frozen_error(state, call_frame);
        return 0;
      }

      if(args.total() != 1) {
        Exception::argument_error(state, 1, args.total());
        return NULL;
      }

      if(kind_of<Class>(mod) && self->reference_p()) {
        // Promote this to use a direct accessor
        if(TypeInfo* ti = state->memory()->find_type_info(self)) {
          TypeInfo::Slots::iterator it = ti->slots.find(access->name()->index());
          if(it != ti->slots.end()) {
            // Found one!
            access->set_executor(ti->slot_accessors[it->second]);
            ti->set_field(state, self, it->second, args.get_argument(0));
            return args.get_argument(0);
          }
        }

        /* Fall through, handle it as a normal ivar. */
        access->set_executor(access_write_regular_ivar);
      }

      self->set_ivar(state, access->name(), args.get_argument(0));
      return args.get_argument(0);
    }

    /* The read case. */
    if(args.total() != 0) {
      Exception::argument_error(state, 0, args.total());
      return NULL;
    }

    if(kind_of<Class>(mod) && self->reference_p()) {
      // Promote this to use a direct accessor
      if(TypeInfo* ti = state->memory()->find_type_info(self)) {
        TypeInfo::Slots::iterator it = ti->slots.find(access->name()->index());
        if(it != ti->slots.end()) {
          // Found one!
          access->set_executor(ti->slot_accessors[it->second]);
          return ti->get_field(state, self, it->second);
        }
      }
      // Ok, its a table ivar, setup fast access for next time.
      access->set_executor(access_read_regular_ivar);
    }

    return self->get_ivar(state, access->name());
  }
  Object* AccessVariable::access_read_regular_ivar(STATE, CallFrame* call_frame, Executable* exec, Module* mod,
                                         Arguments& args) {
    AccessVariable* access = as<AccessVariable>(exec);
    if(unlikely(args.total() != 0)) {
      Exception::argument_error(state, 0, args.total());
      return NULL;
    }

    Object* recv = args.recv();
    return recv->get_ivar(state, access->name());
  }
  void test_access_variable_is_slot() {
    AccessVariable* av = AccessVariable::allocate(state);

    Arguments args(state->symbol("blah"), G(object));

    av->name(state, state->symbol("@module_name"));

    Object* ret = av->access_execute(state, av, G(object), args);
    TS_ASSERT(try_as<Symbol>(ret));

    TS_ASSERT_EQUALS(std::string("Object"), as<Symbol>(ret)->cpp_str(state));
  }
Exemple #5
0
    void test_access_variable_is_slot() {
        AccessVariable* av = AccessVariable::allocate(state);
        CallFrame cf;

        Dispatch dis(state->symbol("blah"), G(object), av);
        Arguments args(G(object), 0, 0);

        av->name(state, state->symbol("@name"));

        Object* ret = av->access_execute(state, &cf, dis, args);
        TS_ASSERT(try_as<Symbol>(ret));

        TS_ASSERT_EQUALS(std::string("Object"), as<Symbol>(ret)->c_str(state));
    }
  void test_access_variable() {
    AccessVariable* av = AccessVariable::allocate(state);

    Arguments args(state->symbol("blah"), G(object));

    av->name(state, state->symbol("@blah"));

    G(object)->set_ivar(state, av->name(), state->symbol("Sweet"));

    Object* ret = av->execute(state, av, G(object), args);
    TS_ASSERT(try_as<Symbol>(ret));

    TS_ASSERT_EQUALS(std::string("Sweet"), as<Symbol>(ret)->cpp_str(state));
  }
  void test_write_variable_is_slot() {
    AccessVariable* av = AccessVariable::allocate(state);

    Symbol* val = state->symbol("Blah");
    Object* ary[1] = {val};
    Arguments args(state->symbol("blah"), G(object), 1, ary);

    av->name(state, state->symbol("@module_name"));
    av->write(state, cTrue);

    Object* ret = av->access_execute(state, av, G(object), args);
    TS_ASSERT_EQUALS(ret, val);

    TS_ASSERT_EQUALS(val, G(object)->module_name());
  }
Exemple #8
0
    void test_access_variable_is_slot() {
        AccessVariable* av = AccessVariable::allocate(state);
        Task* task = Task::create(state, 10);
        Message msg(state);
        msg.recv = G(object);
        msg.method = av;
        msg.use_from_task(task, 0);
        av->name(state, state->symbol("@name"));

        TS_ASSERT(!av->execute(state, task, msg));
        Object* ret = task->pop();
        TS_ASSERT(try_as<Symbol>(ret));

        TS_ASSERT_EQUALS(std::string("Object"), as<Symbol>(ret)->c_str(state));
    }
  void test_write_variable() {
    AccessVariable* av = AccessVariable::allocate(state);

    Symbol* val = state->symbol("Blah");
    Object* ary[1] = {val};
    Arguments args(state->symbol("blah"), G(object), 1, ary);

    av->name(state, state->symbol("@blah"));
    av->write(state, cTrue);

    Object* ret = av->execute(state, av, G(object), args);
    TS_ASSERT_EQUALS(ret, val);

    Symbol* out = as<Symbol>(G(object)->get_ivar(state, av->name()));
    TS_ASSERT_EQUALS(val, out);
  }
Exemple #10
0
    void test_write_variable_is_slot() {
        AccessVariable* av = AccessVariable::allocate(state);

        CallFrame cf;
        Dispatch dis(state->symbol("blah"), G(object), av);
        Symbol* val = state->symbol("Blah");
        Object* ary[1] = {val};
        Arguments args(G(object), 1, ary);

        av->name(state, state->symbol("@name"));
        av->write(state, Qtrue);

        Object* ret = av->access_execute(state, &cf, dis, args);
        TS_ASSERT_EQUALS(ret, val);

        TS_ASSERT_EQUALS(val, G(object)->name());
    }
Exemple #11
0
  Object* AccessVariable::access_read_regular_ivar(STATE, CallFrame* call_frame, Executable* exec, Module* mod,
                                         Arguments& args) {
    AccessVariable* access = as<AccessVariable>(exec);
    if(unlikely(args.total() != 0)) {
      Exception::argument_error(state, 0, args.total());
      return NULL;
    }

    Object* recv = args.recv();

    // Handle packed objects in a unique way.
    if(PackedObject* po = try_as<PackedObject>(recv)) {
      return po->get_packed_ivar(state, access->name());
    }

    return recv->get_table_ivar(state, access->name());
  }
  Object* AccessVariable::access_write_regular_ivar(STATE, CallFrame* call_frame, Executable* exec, Module* mod,
                                         Arguments& args) {
    AccessVariable* access = as<AccessVariable>(exec);
    if(unlikely(args.total() != 1)) {
      Exception::argument_error(state, 1, args.total());
      return NULL;
    }

    Object* recv = args.recv();

    if(CBOOL(recv->frozen_p(state)) && CBOOL(recv->frozen_mod_disallowed(state))) {
      Exception::frozen_error(state, call_frame, recv);
      return 0;
    }

    return recv->set_ivar(state, access->name(), args.get_argument(0));
  }
Exemple #13
0
    void test_write_variable_is_slot() {
        AccessVariable* av = AccessVariable::allocate(state);
        Task* task = Task::create(state, 10);
        Message msg(state);
        msg.recv = G(object);
        msg.method = av;
        msg.use_from_task(task, 0);
        av->name(state, state->symbol("@name"));
        av->write(state, Qtrue);

        Symbol* val = state->symbol("Blah");

        msg.unshift_argument(state, val);

        TS_ASSERT(!av->execute(state, task, msg));
        Object* ret = task->pop();
        TS_ASSERT_EQUALS(ret, val);

        TS_ASSERT_EQUALS(val, G(object)->name());
    }
Exemple #14
0
  Object* AccessVariable::access_write_regular_ivar(STATE, CallFrame* call_frame, Executable* exec, Module* mod,
                                         Arguments& args) {
    AccessVariable* access = as<AccessVariable>(exec);
    if(unlikely(args.total() != 1)) {
      Exception::argument_error(state, 1, args.total());
      return NULL;
    }

    Object* recv = args.recv();

    if(CBOOL(recv->frozen_p(state))) {
      Exception::frozen_error(state, call_frame);
      return 0;
    }

    // Handle packed objects in a unique way.
    if(PackedObject* po = try_as<PackedObject>(recv)) {
      return po->set_packed_ivar(state, access->name(), args.get_argument(0));
    }

    return recv->set_table_ivar(state, access->name(), args.get_argument(0));
  }
Exemple #15
0
  /* Run when an AccessVariable is executed. Uses the details in msg.method
   * to access instance variables of msg.recv */
  ExecuteStatus AccessVariable::access_execute(STATE, Task* task, Message& msg) {
    AccessVariable* access = as<AccessVariable>(msg.method);

    /* The writer case. */
    if(access->write()->true_p()) {
      if(msg.args() != 1) {
        Exception::argument_error(state, 1, msg.args());
      }

      /* Fall through, handle it as a normal ivar. */
      msg.recv->set_ivar(state, access->name(), msg.get_argument(0));
      task->primitive_return(msg.get_argument(0), msg);
      return cExecuteContinue;
    }

    /* The read case. */
    if(msg.args() != 0) {
      Exception::argument_error(state, 0, msg.args());
    } else {
      task->primitive_return(msg.recv->get_ivar(state, access->name()), msg);
    }

    return cExecuteContinue;
  }
Exemple #16
0
 AccessVariable* AccessVariable::allocate(STATE) {
   AccessVariable* av = state->new_object<AccessVariable>(G(access_variable));
   av->set_executor(AccessVariable::access_execute);
   return av;
 }