Object* Module::cvar_set(STATE, Symbol* name, Object* value) { if(!name->is_cvar_p(state)->true_p()) return Primitives::failure(); check_frozen(state); Module* mod = this; Module* mod_to_query; while(!mod->nil_p()) { mod_to_query = get_module_to_query(mod); if(mod_to_query->table_ivar_defined(state, name)->true_p()) { mod_to_query->set_table_ivar(state, name, value); return value; } mod = mod->superclass(); } mod = this; mod_to_query = get_module_to_query(mod); mod_to_query->set_ivar(state, name, value); return value; }
Object* MethodTable::alias(STATE, Symbol* name, Symbol* vis, Symbol* orig_name, Object* orig_method, Module* orig_mod) { check_frozen(state); utilities::thread::SpinLock::LockGuard lg(lock_); Executable* orig_exec; if(Alias* alias = try_as<Alias>(orig_method)) { orig_exec = alias->original_exec(); orig_mod = alias->original_module(); orig_name = alias->original_name(); } else if(orig_method->nil_p()) { orig_exec = nil<Executable>(); } else { orig_exec = as<Executable>(orig_method); } Alias* method = Alias::create(state, orig_name, orig_mod, orig_exec); native_int num_entries = entries_->to_native(); native_int num_bins = bins_->to_native(); if(max_density_p(num_entries, num_bins)) { redistribute(state, num_bins <<= 1); } native_int bin = find_bin(key_hash(name), num_bins); MethodTableBucket* entry = try_as<MethodTableBucket>(values_->at(state, bin)); MethodTableBucket* last = NULL; while(entry) { if(entry->name() == name) { entry->method_id(state, nil<String>()); entry->method(state, method); entry->scope(state, cNil); entry->serial(state, Fixnum::from(0)); entry->visibility(state, vis); return name; } last = entry; entry = try_as<MethodTableBucket>(entry->next()); } if(last) { last->next(state, MethodTableBucket::create( state, name, nil<String>(), method, cNil, Fixnum::from(0), vis)); } else { values_->put(state, bin, MethodTableBucket::create( state, name, nil<String>(), method, cNil, Fixnum::from(0), vis)); } entries(state, Fixnum::from(num_entries + 1)); return name; }
Object* MethodTable::store(STATE, Symbol* name, Object* exec, Symbol* vis) { check_frozen(state); utilities::thread::SpinLock::LockGuard lg(lock_); Executable* method; if(exec->nil_p()) { method = nil<Executable>(); } else { if(Alias* stored_alias = try_as<Alias>(exec)) { lock_.unlock(); Object* res = alias(state, name, vis, stored_alias->original_name(), stored_alias->original_exec(), stored_alias->original_module()); lock_.lock(); return res; } else { method = as<Executable>(exec); } } native_int num_entries = entries_->to_native(); native_int num_bins = bins_->to_native(); if(max_density_p(num_entries, num_bins)) { redistribute(state, num_bins <<= 1); } native_int bin = find_bin(key_hash(name), num_bins); MethodTableBucket* entry = try_as<MethodTableBucket>(values_->at(state, bin)); MethodTableBucket* last = NULL; while(entry) { if(entry->name() == name) { entry->method(state, method); entry->visibility(state, vis); return name; } last = entry; entry = try_as<MethodTableBucket>(entry->next()); } if(last) { last->next(state, MethodTableBucket::create(state, name, method, vis)); } else { values_->put(state, bin, MethodTableBucket::create(state, name, method, vis)); } entries(state, Fixnum::from(num_entries + 1)); return name; }
Object* Thread::locals_remove(STATE, Symbol* key) { check_frozen(state); if(state->vm() != vm()) { return locals()->remove(state, key); } Fiber* fib = state->vm()->current_fiber.get(); if(fib->nil_p() || fib->root_p()) { return locals()->remove(state, key); } if(fib->locals()->nil_p()) { return cNil; } return fib->locals()->remove(state, key); }
Object* Thread::locals_store(STATE, Symbol* key, Object* value) { /* * If we're not trying to set values on the current thread, * we will set thread locals anyway and not use fiber locals. */ check_frozen(state); if(state->vm() != vm()) { return locals()->store(state, key, value); } Fiber* fib = state->vm()->current_fiber.get(); if(fib->nil_p() || fib->root_p()) { return locals()->store(state, key, value); } if(fib->locals()->nil_p()) { fib->locals(state, LookupTable::create(state)); } return fib->locals()->store(state, key, value); }
Executable* MethodTable::remove(STATE, Symbol* name) { check_frozen(state); utilities::thread::SpinLock::LockGuard lg(lock_); native_int num_entries = entries_->to_native(); native_int num_bins = bins_->to_native(); if(min_density_p(num_entries, num_bins) && (num_bins >> 1) >= METHODTABLE_MIN_SIZE) { redistribute(state, num_bins >>= 1); } native_int bin = find_bin(key_hash(name), num_bins); MethodTableBucket* entry = try_as<MethodTableBucket>(values_->at(state, bin)); MethodTableBucket* last = NULL; while(entry) { if(entry->name() == name) { Executable* val = entry->method(); if(last) { last->next(state, entry->next()); } else { values_->put(state, bin, entry->next()); } entries(state, Fixnum::from(entries_->to_native() - 1)); return val; } last = entry; entry = try_as<MethodTableBucket>(entry->next()); } return nil<Executable>(); }
Object* Thread::fiber_variable_set(STATE, Symbol* key, Object* value) { check_frozen(state); return current_fiber()->locals()->store(state, key, value); }