void ValueStack::clear_stores() { ValueStack* stack = this; while (stack != NULL) { for (int i = 0; i < stack->_stores.length(); i++) stack->_stores.at_put(i, NULL); stack = stack->caller_state(); } }
void Scumm::v6::Scummv6StoreInstruction::processInst(Function&, ValueStack &stack, Engine*, CodeGenerator *codeGen) { Scummv6CodeGenerator *cg = (Scummv6CodeGenerator *)codeGen; switch (_opcode) { case 0x42: // writeByteVar case 0x43: // writeWordVar { ValuePtr p = new VarValue(cg->decodeVarName(static_cast<uint16>(_params[0]->getUnsigned()))); cg->writeAssignment(p, stack.pop()); } break; case 0x46: // byteArrayWrite case 0x47: // wordArrayWrite { ValuePtr value = stack.pop(); ValueList idxs; idxs.push_back(stack.pop()); ValuePtr p = new ArrayValue(cg->decodeArrayName(static_cast<uint16>(_params[0]->getUnsigned())), idxs); cg->writeAssignment(p, value); } break; case 0x4A: // byteArrayIndexedWrite case 0x4B: // wordArrayIndexedWrite { ValuePtr value = stack.pop(); ValueList idxs; idxs.push_front(stack.pop()); idxs.push_front(stack.pop()); ValuePtr p = new ArrayValue(cg->decodeArrayName(static_cast<uint16>(_params[0]->getUnsigned())), idxs); cg->writeAssignment(p, value); } break; } }
void ValueStack::eliminate_all_scope_stores(int bci) { ValueStack* stack = this; while (stack != NULL) { stack->eliminate_stores(bci); stack = stack->caller_state(); } }
void Scumm::v6::Scummv6ArrayOpInstruction::processInst(Function&, ValueStack &stack, Engine*, CodeGenerator *codeGen) { Scummv6CodeGenerator *cg = (Scummv6CodeGenerator *)codeGen; switch (_opcode) { case 0xA4CD: // arrayOp_assignString { ValuePtr value = _params[1]; ValueList idxs; idxs.push_front(stack.pop()); ValuePtr p = new ArrayValue(cg->decodeArrayName(static_cast<uint16>(_params[0]->getUnsigned())), idxs); cg->writeAssignment(p, value); } break; case 0xA4D0: // arrayOp_assignIntList { ValueList idxs; idxs.push_front(stack.pop()); ValuePtr value = cg->createListValue(); ValuePtr p = new ArrayValue(cg->decodeArrayName(static_cast<uint16>(_params[0]->getUnsigned())), idxs); cg->writeAssignment(p, value); } break; case 0xA4D4: // arrayOp_assign2DimList { ValueList idxs; idxs.push_front(stack.pop()); ValuePtr value = cg->createListValue(); idxs.push_front(stack.pop()); ValuePtr p = new ArrayValue(cg->decodeArrayName(static_cast<uint16>(_params[0]->getUnsigned())), idxs); cg->writeAssignment(p, value); } break; } }
ValueStack* ValueStack::push_scope(IRScope* scope) { assert(scope->caller() == _scope, "scopes must have caller/callee relationship"); ValueStack* res = new ValueStack(scope, scope->method()->max_locals(), max_stack_size() + scope->method()->max_stack()); // Preserves stack and monitors. res->_stack.appendAll(&_stack); res->_locks.appendAll(&_locks); assert(res->_stack.size() <= res->max_stack_size(), "stack overflow"); return res; }
// Index caller states in s, where 0 is the oldest, 1 its callee, etc. // Return NULL if n is too large. // Returns the caller_bci for the next-younger state, also. static ValueStack* nth_oldest(ValueStack* s, int n, int& bci_result) { ValueStack* t = s; for (int i = 0; i < n; i++) { if (t == NULL) break; t = t->caller_state(); } if (t == NULL) return NULL; for (;;) { ValueStack* tc = t->caller_state(); if (tc == NULL) return s; t = tc; bci_result = tc->bci(); s = s->caller_state(); } }
void Scumm::v6::Scummv6IncDecInstruction::processInst(Function&, ValueStack &stack, Engine*, CodeGenerator *codeGen) { Scummv6CodeGenerator *cg = (Scummv6CodeGenerator *)codeGen; switch (_opcode) { case 0x4E: // byteVarInc case 0x4F: // wordVarInc case 0x56: // byteVarDec case 0x57: // wordVarDec { std::stringstream s; ValuePtr p = new UnaryOpValue(new VarValue(cg->decodeVarName(static_cast<uint16>(_params[0]->getUnsigned()))), _codeGenData, true); s << p << ";"; cg->addOutputLine(s.str()); } break; case 0x52: // byteArrayInc case 0x53: // wordArrayInc case 0x5A: // byteArrayDec case 0x5B: // wordArrayDec { std::stringstream s; ValueList idxs; idxs.push_front(stack.pop()); ValuePtr p = new UnaryOpValue(new ArrayValue(cg->decodeVarName(static_cast<uint16>(_params[0]->getUnsigned())), idxs), _codeGenData, true); s << p << ";"; cg->addOutputLine(s.str()); } break; } }
bool lua_details::listVirtualStack(lua_State* L, ValueStack& stack, size_t table_size_limit) { int size= lua_gettop(L); stack.clear(); stack.reserve(size); for (int idx= size - 1; idx > 0; --idx) { Value v(L, idx, 1, table_size_limit); stack.push_back(v); } return true; }
void CFGPrinterOutput::print_state(BlockBegin* block) { print_begin("states"); InstructionPrinter ip(true, output()); ValueStack* state = block->state(); int index; Value value; if (state->stack_size() > 0) { print_begin("stack"); print("size %d", state->stack_size()); for_each_stack_value(state, index, value) { ip.print_phi(index, value, block); print_operand(value); output()->cr(); }
void Scumm::v6::Scummv6LoadInstruction::processInst(Function&, ValueStack &stack, Engine*, CodeGenerator *codeGen) { Scummv6CodeGenerator *cg = (Scummv6CodeGenerator *)codeGen; switch (_opcode) { case 0x00: // pushByte case 0x01: // pushWord stack.push(_params[0]); break; case 0x02: // pushByteVar case 0x03: // pushWordVar stack.push(new VarValue(cg->decodeVarName(static_cast<uint16>(_params[0]->getUnsigned())))); break; case 0x06: // byteArrayRead case 0x07: // wordArrayRead { ValueList idxs; idxs.push_front(stack.pop()); stack.push(new ArrayValue(cg->decodeArrayName(static_cast<uint16>(_params[0]->getUnsigned())), idxs)); break; } case 0x0A: // byteArrayIndexedRead case 0x0B: // wordArrayIndexedRead { ValueList idxs; idxs.push_front(stack.pop()); idxs.push_front(stack.pop()); stack.push(new ArrayValue(cg->decodeArrayName(static_cast<uint16>(_params[0]->getUnsigned())), idxs)); break; } } }
void CFGPrinterOutput::print_state(BlockBegin* block) { print_begin("states"); InstructionPrinter ip(true, output()); ValueStack* state = block->state(); int index; Value value; for_each_state(state) { print_begin("locals"); print("size %d", state->locals_size()); print("method \"%s\"", method_name(state->scope()->method())); for_each_local_value(state, index, value) { ip.print_phi(index, value, block); print_operand(value); output()->cr(); } print_end("locals"); if (state->stack_size() > 0) { print_begin("stack"); print("size %d", state->stack_size()); print("method \"%s\"", method_name(state->scope()->method())); for_each_stack_value(state, index, value) { ip.print_phi(index, value, block); print_operand(value); output()->cr(); }
void LIR_Assembler::record_non_safepoint_debug_info() { int pc_offset = _pending_non_safepoint_offset; ValueStack* vstack = debug_info(_pending_non_safepoint); int bci = vstack->bci(); DebugInformationRecorder* debug_info = compilation()->debug_info_recorder(); assert(debug_info->recording_non_safepoints(), "sanity"); debug_info->add_non_safepoint(pc_offset); // Visit scopes from oldest to youngest. for (int n = 0; ; n++) { int s_bci = bci; ValueStack* s = nth_oldest(vstack, n, s_bci); if (s == NULL) break; IRScope* scope = s->scope(); //Always pass false for reexecute since these ScopeDescs are never used for deopt debug_info->describe_scope(pc_offset, scope->method(), s->bci(), false/*reexecute*/); } debug_info->end_non_safepoint(pc_offset); }
Value expression::eval(Value &ret) { ValueStack valstack; String str_oper; str_oper="oper"; POSITION pos=m_postfix.get_top_position(); for(; pos; pos=m_postfix.get_next(pos)){ const char*s=m_postfix.get(pos); if(s[0]=='%' || isalpha(s[0]) ) { //ValueRef vref(getworld()->var_get(s)); valstack.add(getworld()->var_get(s)); } else if (isdigit(s[0])){ valstack.add()=str_to_real(s); } else { _oper* p; if(s[0]=='\'') p=getworld()->oper_get(s+1); else p=getworld()->oper_get(str_oper+s); p->eval(valstack) ; } } ret=valstack.get_last(); valstack.remove(); return ret; }
ValueStack* ValueStack::pop_scope(bool should_eliminate_stores, int bci) { assert(_scope->caller() != NULL, "scope must have caller"); IRScope* scope = _scope->caller(); int max_stack = max_stack_size() - _scope->method()->max_stack(); assert(max_stack >= 0, "stack underflow"); ValueStack* res = new ValueStack(scope, scope->method()->max_locals(), max_stack); // Preserves stack and monitors. Restores local and store state from caller scope. res->_stack.appendAll(&_stack); res->_locks.appendAll(&_locks); ValueStack* caller = caller_state(); if (caller != NULL) { for (int i = 0; i < caller->_locals.length(); i++) { res->_locals.at_put(i, caller->_locals.at(i)); res->_stores.at_put(i, caller->_stores.at(i)); } assert(res->_locals.length() == res->scope()->method()->max_locals(), "just checking"); assert(res->_stores.length() == res->scope()->method()->max_locals(), "just checking"); } assert(res->_stack.size() <= res->max_stack_size(), "stack overflow"); if (EliminateStores && should_eliminate_stores) eliminate_stores(bci); return res; }
void Scumm::v6::Scummv6StackInstruction::processInst(Function&, ValueStack &stack, Engine*, CodeGenerator*) { stack.pop(); }
void Scumm::v6::Scummv6CondJumpInstruction::processInst(Function&, ValueStack &stack, Engine*, CodeGenerator*) { if (_opcode == 0x5D) // jumpFalse stack.push(stack.pop()->negate()); }
void LoopInvariantCodeMotion::process_block(BlockBegin* block) { TRACE_VALUE_NUMBERING(tty->print_cr("processing block B%d", block->block_id())); Instruction* prev = block; Instruction* cur = block->next(); while (cur != NULL) { // determine if cur instruction is loop invariant // only selected instruction types are processed here bool cur_invariant = false; if (cur->as_Constant() != NULL) { cur_invariant = !cur->can_trap(); } else if (cur->as_ArithmeticOp() != NULL || cur->as_LogicOp() != NULL || cur->as_ShiftOp() != NULL) { assert(cur->as_Op2() != NULL, "must be Op2"); Op2* op2 = (Op2*)cur; cur_invariant = !op2->can_trap() && is_invariant(op2->x()) && is_invariant(op2->y()); } else if (cur->as_LoadField() != NULL) { LoadField* lf = (LoadField*)cur; // deoptimizes on NullPointerException cur_invariant = !lf->needs_patching() && !lf->field()->is_volatile() && !_short_loop_optimizer->has_field_store(lf->field()->type()->basic_type()) && is_invariant(lf->obj()) && _insert_is_pred; } else if (cur->as_ArrayLength() != NULL) { ArrayLength *length = cur->as_ArrayLength(); cur_invariant = is_invariant(length->array()); } else if (cur->as_LoadIndexed() != NULL) { LoadIndexed *li = (LoadIndexed *)cur->as_LoadIndexed(); cur_invariant = !_short_loop_optimizer->has_indexed_store(as_BasicType(cur->type())) && is_invariant(li->array()) && is_invariant(li->index()) && _insert_is_pred; } if (cur_invariant) { // perform value numbering and mark instruction as loop-invariant _gvn->substitute(cur); if (cur->as_Constant() == NULL) { // ensure that code for non-constant instructions is always generated cur->pin(); } // remove cur instruction from loop block and append it to block before loop Instruction* next = cur->next(); Instruction* in = _insertion_point->next(); _insertion_point = _insertion_point->set_next(cur); cur->set_next(in); // Deoptimize on exception cur->set_flag(Instruction::DeoptimizeOnException, true); // Clear exception handlers cur->set_exception_handlers(NULL); TRACE_VALUE_NUMBERING(tty->print_cr("Instruction %c%d is loop invariant", cur->type()->tchar(), cur->id())); if (cur->state_before() != NULL) { cur->set_state_before(_state->copy()); } if (cur->exception_state() != NULL) { cur->set_exception_state(_state->copy()); } cur = prev->set_next(next); } else { prev = cur; cur = cur->next(); } } }
void InstructionPrinter::do_BlockBegin(BlockBegin* x) { // print block id BlockEnd* end = x->end(); output()->print("B%d ", x->block_id()); // print flags bool printed_flag = false; if (x->is_set(BlockBegin::std_entry_flag)) { if (!printed_flag) output()->print("("); output()->print("S"); printed_flag = true; } if (x->is_set(BlockBegin::osr_entry_flag)) { if (!printed_flag) output()->print("("); output()->print("O"); printed_flag = true; } if (x->is_set(BlockBegin::exception_entry_flag)) { if (!printed_flag) output()->print("("); output()->print("E"); printed_flag = true; } if (x->is_set(BlockBegin::subroutine_entry_flag)) { if (!printed_flag) output()->print("("); output()->print("s"); printed_flag = true; } if (x->is_set(BlockBegin::parser_loop_header_flag)) { if (!printed_flag) output()->print("("); output()->print("LH"); printed_flag = true; } if (x->is_set(BlockBegin::backward_branch_target_flag)) { if (!printed_flag) output()->print("("); output()->print("b"); printed_flag = true; } if (x->is_set(BlockBegin::was_visited_flag)) { if (!printed_flag) output()->print("("); output()->print("V"); printed_flag = true; } if (printed_flag) output()->print(") "); // print block bci range output()->print("[%d, %d]",x->bci(),(end==NULL?InvocationEntryBci:end->bci())); // print block successors if (end != NULL && end->number_of_sux() > 0) { output()->print(" ->"); for (int i = 0; i < end->number_of_sux(); i++) { output()->print(" B%d", end->sux_at(i)->block_id()); } } // print exception handlers if (x->number_of_exception_handlers() > 0) { output()->print(" (xhandlers "); for (int i = 0; i < x->number_of_exception_handlers(); i++) { if (i > 0) output()->print(" "); output()->print("B%d", x->exception_handler_at(i)->block_id()); } output()->put(')'); } // print dominator block if (x->dominator() != NULL) { output()->print(" dom B%d", x->dominator()->block_id()); } // print predecessors and successors if (x->successors()->length() > 0) { output()->print(" sux:"); for (int i = 0; i < x->successors()->length(); i ++) { output()->print(" B%d", x->successors()->at(i)->block_id()); } } if (x->number_of_preds() > 0) { output()->print(" pred:"); for (int i = 0; i < x->number_of_preds(); i ++) { output()->print(" B%d", x->pred_at(i)->block_id()); } } if (!_print_phis) { return; } // print phi functions bool has_phis_in_locals = false; bool has_phis_on_stack = false; if (x->end() && x->end()->state()) { ValueStack* state = x->state(); int i = 0; while (!has_phis_on_stack && i < state->stack_size()) { Value v = state->stack_at_inc(i); has_phis_on_stack = is_phi_of_block(v, x); } do { for (i = 0; !has_phis_in_locals && i < state->locals_size();) { Value v = state->local_at(i); has_phis_in_locals = is_phi_of_block(v, x); // also ignore illegal HiWords if (v && !v->type()->is_illegal()) i += v->type()->size(); else i ++; } state = state->caller_state(); } while (state != NULL); } // print values in locals if (has_phis_in_locals) { output()->cr(); output()->print_cr("Locals:"); ValueStack* state = x->state(); do { for (int i = 0; i < state->locals_size();) { Value v = state->local_at(i); if (v) { print_phi(i, v, x); output()->cr(); // also ignore illegal HiWords i += (v->type()->is_illegal() ? 1 : v->type()->size()); } else { i ++; } } output()->cr(); state = state->caller_state(); } while (state != NULL); } // print values on stack if (has_phis_on_stack) { output()->print_cr("Stack:"); int i = 0; while (i < x->state()->stack_size()) { int o = i; Value v = x->state()->stack_at_inc(i); if (v) { print_phi(o, v, x); output()->cr(); } } } }