VariableScope* VariableScope::synthesize(STATE, CompiledMethod* method, Module* module, Object* parent, Object* self, Object* block, Tuple* locals) { VariableScope* scope = state->new_object<VariableScope>(G(variable_scope)); scope->block(state, block); scope->module(state, module); scope->method(state, method); if(VariableScope* vs = try_as<VariableScope>(parent)) { scope->parent(state, vs); } else { scope->parent(state, nil<VariableScope>()); } scope->heap_locals(state, locals); scope->last_match(state, cNil); scope->self(state, self); scope->number_of_locals_ = locals->num_fields(); scope->isolated_ = true; scope->locals_ = 0; scope->block_as_method_ = 0; return scope; }
VariableScope* StackVariables::create_heap_alias(STATE, CallFrame* call_frame, bool full) { if(on_heap_) return on_heap_; VMMethod* vmm = call_frame->cm->backend_method(); VariableScope* scope = state->new_struct<VariableScope>( G(variable_scope), vmm->number_of_locals * sizeof(Object*)); if(parent_) { scope->parent(state, parent_); } else { scope->parent(state, (VariableScope*)Qnil); } scope->self(state, self_); scope->block(state, block_); scope->module(state, module_); scope->method(state, call_frame->cm); scope->number_of_locals_ = vmm->number_of_locals; if(full) { scope->isolated_ = false; scope->point_locals_to(locals_); } else { scope->isolated_ = true; scope->point_locals_to(scope->heap_locals_); } on_heap_ = scope; return scope; }
Symbol* original_name() { if(multiple_scopes_p()) { if(block_as_method_p()) return cm->name(); return top_scope_->method()->name(); } return cm->name(); }
VariableScope* StackVariables::create_heap_alias(STATE, CallFrame* call_frame, bool full) { if(on_heap_) return on_heap_; MachineCode* mcode = call_frame->compiled_code->machine_code(); VariableScope* scope = state->memory()->new_object<VariableScope>(state, G(variable_scope)); if(parent_) { scope->parent(state, parent_); } else { scope->parent(state, nil<VariableScope>()); } scope->self(state, self_); scope->block(state, block_); scope->module(state, module_); scope->method(state, call_frame->compiled_code); scope->heap_locals(state, nil<Tuple>()); scope->last_match(state, last_match_); scope->fiber(state, state->vm()->thread()->current_fiber()); scope->number_of_locals(mcode->number_of_locals); scope->isolated(0); scope->flags(call_frame->flags); scope->_lock_.init(); if(!full) { scope->isolated(1); scope->heap_locals(state, Tuple::create(state, mcode->number_of_locals)); for(int i = 0; i < scope->number_of_locals(); i++) { scope->set_local(state, i, locals_[i]); } } scope->locals(locals_); scope->dynamic_locals(state, nil<LookupTable>()); on_heap_ = scope; return scope; }
Object* rbx_zsuper_send(STATE, CallFrame* call_frame, Symbol* name, Object* block) { Object* const recv = call_frame->self(); VariableScope* scope = call_frame->method_scope(state); assert(scope); VMMethod* v = scope->method()->backend_method(); Object* splat_obj = 0; Array* splat = 0; size_t arg_count = v->total_args; if(v->splat_position >= 0) { splat_obj = scope->get_local(state, v->splat_position); splat = try_as<Array>(splat_obj); if(splat) { arg_count += splat->size(); } else { arg_count++; } } Tuple* tup = Tuple::create(state, arg_count); for(int i = 0; i < v->total_args; i++) { tup->put(state, i, scope->get_local(state, i)); } if(splat) { for(size_t i = 0; i < splat->size(); i++) { tup->put(state, i + v->total_args, splat->get(state, i)); } } else if(splat_obj) { tup->put(state, v->total_args, splat_obj); } Arguments out_args(name, recv, block, arg_count, 0); out_args.use_tuple(tup, arg_count); LookupData lookup(recv, call_frame->module()->superclass(), G(sym_private)); Dispatch dis(name); return dis.send(state, call_frame, lookup, out_args, eSuper); }
Object* rbx_zsuper_send(STATE, CallFrame* call_frame, CallSite* call_site, Object* block) { Object* const recv = call_frame->self(); VariableScope* scope = call_frame->method_scope(state); assert(scope); MachineCode* v = scope->method()->machine_code(); Object* splat_obj = 0; Array* splat = 0; size_t arg_count = v->total_args; if(v->splat_position >= 0) { splat_obj = scope->get_local(state, v->splat_position); splat = try_as<Array>(splat_obj); if(splat) { arg_count += splat->size(); } else { arg_count++; } } Tuple* tup = Tuple::create_dirty(state, arg_count); for(int i = 0; i < v->total_args; i++) { tup->put(state, i, scope->get_local(state, i)); } if(splat) { for(native_int i = 0; i < splat->size(); i++) { tup->put(state, i + v->total_args, splat->get(state, i)); } } else if(splat_obj) { tup->put(state, v->total_args, splat_obj); } Arguments out_args(call_site->name(), recv, block, arg_count, 0); out_args.use_tuple(tup, arg_count); return call_site->execute(state, call_frame, out_args); }
VariableScope* StackVariables::create_heap_alias(STATE, CallFrame* call_frame, bool full) { if(on_heap_) return on_heap_; MachineCode* mcode = call_frame->compiled_code->machine_code(); VariableScope* scope = state->new_object_dirty<VariableScope>(G(variable_scope)); if(parent_) { scope->parent(state, parent_); } else { scope->parent(state, nil<VariableScope>()); } scope->self(state, self_); scope->block(state, block_); scope->module(state, module_); scope->method(state, call_frame->compiled_code); scope->heap_locals(state, Tuple::create(state, mcode->number_of_locals)); scope->last_match(state, last_match_); scope->fiber(state, state->vm()->current_fiber.get()); scope->number_of_locals_ = mcode->number_of_locals; if(full) { scope->isolated_ = false; } else { scope->isolated_ = true; } scope->locals_ = locals_; scope->dynamic_locals(state, nil<LookupTable>()); scope->set_block_as_method(call_frame->block_as_method_p()); on_heap_ = scope; return scope; }
VariableScope* VariableScope::promote(STATE) { VariableScope* scope = state->new_struct<VariableScope>( G(variable_scope), number_of_locals_ * sizeof(Object*)); scope->block(state, block_); scope->method(state, method_); scope->module(state, module_); if(parent_) { scope->parent(state, parent_); } else { scope->parent(state, (VariableScope*)Qnil); } scope->self(state, self_); scope->number_of_locals_ = number_of_locals_; for(int i = 0; i < number_of_locals_; i++) { scope->set_local(state, i, locals_[i]); } return scope; }
VariableScope* VariableScope::synthesize(STATE, CompiledCode* method, Module* module, Object* parent, Object* self, Object* block, Tuple* locals) { VariableScope* scope = state->memory()->new_object<VariableScope>(state, G(variable_scope)); scope->block(state, block); scope->module(state, module); scope->method(state, method); if(VariableScope* vs = try_as<VariableScope>(parent)) { scope->parent(state, vs); } else { scope->parent(state, nil<VariableScope>()); } scope->heap_locals(state, locals); scope->self(state, self); scope->number_of_locals(locals->num_fields()); return scope; }
VariableScope* StackVariables::create_heap_alias(STATE, CallFrame* call_frame, bool full) { if(on_heap_) return on_heap_; VMMethod* vmm = call_frame->cm->backend_method(); VariableScope* scope = state->new_object<VariableScope>(G(variable_scope)); if(parent_) { scope->parent(state, parent_); } else { scope->parent(state, nil<VariableScope>()); } scope->self(state, self_); scope->block(state, block_); scope->module(state, module_); scope->method(state, call_frame->cm); scope->heap_locals(state, Tuple::create(state, vmm->number_of_locals)); scope->last_match(state, last_match_); scope->number_of_locals_ = vmm->number_of_locals; if(full) { scope->isolated_ = false; } else { scope->isolated_ = true; } scope->locals_ = locals_; scope->set_block_as_method(call_frame->block_as_method_p()); on_heap_ = scope; return scope; }
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); }