void MachineCode::initialize_caches(STATE, CompiledCode* original, int sends) { number_of_caches_ = sends; caches = new InlineCache[sends]; int which = 0; bool allow_private = false; bool is_super = false; for(size_t ip = 0; ip < total;) { opcode op = opcodes[ip]; switch(op) { case InstructionSequence::insn_invoke_primitive: { Symbol* name = try_as<Symbol>(original->literals()->at(opcodes[ip + 1])); if(!name) { name = state->symbol("__unknown__"); } InvokePrimitive invoker = Primitives::get_invoke_stub(state, name); opcodes[ip + 1] = reinterpret_cast<intptr_t>(invoker); update_addresses(ip, 1); break; } case InstructionSequence::insn_allow_private: allow_private = true; break; case InstructionSequence::insn_push_const_fast: case InstructionSequence::insn_find_const_fast: original->literals()->put(state, opcodes[ip + 2], GlobalCacheEntry::empty(state)); break; case InstructionSequence::insn_send_super_stack_with_block: case InstructionSequence::insn_send_super_stack_with_splat: case InstructionSequence::insn_zsuper: is_super = true; // fall through case InstructionSequence::insn_check_serial: case InstructionSequence::insn_check_serial_private: case InstructionSequence::insn_call_custom: case InstructionSequence::insn_send_method: case InstructionSequence::insn_send_stack: case InstructionSequence::insn_send_stack_with_block: case InstructionSequence::insn_send_stack_with_splat: case InstructionSequence::insn_meta_send_call: case InstructionSequence::insn_meta_send_op_plus: case InstructionSequence::insn_meta_send_op_minus: case InstructionSequence::insn_meta_send_op_equal: case InstructionSequence::insn_meta_send_op_tequal: case InstructionSequence::insn_meta_send_op_lt: case InstructionSequence::insn_meta_send_op_gt: case InstructionSequence::insn_meta_to_s: { assert(which < sends); InlineCache* cache = &caches[which++]; cache->set_location(ip, this); Symbol* name = try_as<Symbol>(original->literals()->at(opcodes[ip + 1])); if(!name) { name = state->symbol("__unknown__"); } cache->set_name(name); if(op == InstructionSequence::insn_call_custom) { cache->set_call_custom(); } else { if(allow_private) cache->set_is_private(); if(is_super) cache->set_is_super(); if(op == InstructionSequence::insn_send_method) { cache->set_is_vcall(); } } state->shared().ic_registry()->add_cache(state, name, cache); opcodes[ip + 1] = reinterpret_cast<intptr_t>(cache); update_addresses(ip, 1); is_super = false; allow_private = false; } } ip += InstructionSequence::instruction_width(op); } }