oop slotsMap::copy_add_argument_slot(slotsOop obj, stringOop name, slotType type, oop contents, oop anno, bool mustAllocate) { assert_smi(contents, "arg data must be position"); if (!name->is_unary()) return ErrorCodes::vmString_prim_error(ARGUMENTCOUNTERROR); slotDesc* old = find_slot(name); slotsOop result; if (old == NULL) result= obj; else if (old->is_arg_slot()) { // No need to remove and reinsert because order is the same. // Only the annotation might be really different. // The index will be off by one (assumes that added slot is new) assert(smiOop(contents)->value() == smiOop(old->data)->value() + 1, "arg index wrong"); return change_slot(obj, old, type, old->data, anno, mustAllocate); } else { result= (slotsOop)copy_remove_slot(obj, name, mustAllocate); if (oop(result) == failedAllocationOop || result->is_mark()) return result; assert(result->is_slots(), "just checking"); } assert(smiOop(contents)->value() == arg_count(), "arg index wrong"); return ((slotsMap*)result->map())->copy_add_new_slot(result, name, type, contents, anno, mustAllocate); }
PRIM_DECL_3(doubleByteArrayPrimitives::atPut, oop receiver, oop index, oop value) { PROLOGUE_3("atPut", receiver, index, value); ASSERT_RECEIVER; // check index type if (!index->is_smi()) return markSymbol(vmSymbols::first_argument_has_wrong_type()); // check value type if (!value->is_smi()) return markSymbol(vmSymbols::second_argument_has_wrong_type()); // check index value if (!doubleByteArrayOop(receiver)->is_within_bounds(smiOop(index)->value())) return markSymbol(vmSymbols::out_of_bounds()); // check value as double byte unsigned int v = (unsigned int) smiOop(value)->value(); if (v >= (1<<16)) return markSymbol(vmSymbols::value_out_of_range()); // do the operation doubleByteArrayOop(receiver)->doubleByte_at_put(smiOop(index)->value(), v); return receiver; }
PRIM_DECL_2(doubleByteArrayPrimitives::allocateSize, oop receiver, oop argument) { PROLOGUE_2("allocateSize", receiver, argument) assert(receiver->is_klass() && klassOop(receiver)->klass_part()->oop_is_doubleByteArray(), "receiver must double byte array class"); if (!argument->is_smi()) markSymbol(vmSymbols::first_argument_has_wrong_type()); if (smiOop(argument)->value() < 0) return markSymbol(vmSymbols::negative_size()); klassOop k = klassOop(receiver); int ni_size = k->klass_part()->non_indexable_size(); int obj_size = ni_size + 1 + roundTo(smiOop(argument)->value() * 2, oopSize) / oopSize; // allocate doubleByteArrayOop obj = as_doubleByteArrayOop(Universe::allocate(obj_size, (memOop*)&k)); // header memOop(obj)->initialize_header(true, k); // instance variables memOop(obj)->initialize_body(memOopDesc::header_size(), ni_size); // indexables oop* base = (oop*) obj->addr(); oop* end = base + obj_size; // %optimized 'obj->set_length(size)' base[ni_size] = argument; // %optimized 'for (int index = 1; index <= size; index++) // obj->doubleByte_at_put(index, 0)' base = &base[ni_size+1]; while (base < end) *base++ = (oop) 0; return obj; }
PRIM_DECL_2(doubleValueArrayPrimitives::allocateSize, oop receiver, oop argument) { PROLOGUE_2("allocateSize", receiver, argument) assert(receiver->is_klass() && klassOop(receiver)->klass_part()->oop_is_doubleValueArray(), "receiver must double byte array class"); if (!argument->is_smi()) markSymbol(vmSymbols::first_argument_has_wrong_type()); if (smiOop(argument)->value() < 0) return markSymbol(vmSymbols::negative_size()); int length = smiOop(argument)->value(); klassOop k = klassOop(receiver); int ni_size = k->klass_part()->non_indexable_size(); int obj_size = ni_size + 1 + roundTo(length * sizeof(double), oopSize) / oopSize; // allocate doubleValueArrayOop obj = as_doubleValueArrayOop(Universe::allocate(obj_size, (memOop*)&k)); // header memOop(obj)->initialize_header(true, k); // instance variables memOop(obj)->initialize_body(memOopDesc::header_size(), ni_size); obj->set_length(length); for (int index = 1; index <= length; index++) { obj->double_at_put(index, 0.0); } return obj; }
oop set_sic_params_prim(oop r, char* which, objVectorOop params, void* FH) { ResourceMark rm; IntBList* l = stringToList(which); if (!l) { failure(FH, SIC_PARAMS_ERROR_MSG); return 0; } fint len = params->length(); fint *n= NEW_RESOURCE_ARRAY(fint, len); fint i; for (i = 0; i < len; i++) { oop param = params->obj_at(i); if (!param->is_smi() || smiOop(param)->value() < 1) { char msg[BUFSIZ]; sprintf(msg, "arg2[%ld]: invalid parameter (not a positive integer)", long(i)); failure(FH, msg); return 0; } n[i] = smiOop(param)->value(); } oop res = get_sic_params_prim(r, which, NULL); l->clear(); for (i = 0; i < len; i++) l->push(n[i]); return res; }
slotsOop slotsMap::copy_remove_one_slot(slotsOop obj, slotDesc *slot, bool mustAllocate) { assert_slots(obj, "object isn't a slotsOop"); assert(!obj->is_string(), "cannot clone strings!"); assert(slot >= slots() && slot < slotsMap::slot(length_slots()), "slotDesc not part of map"); slotsMap* new_map= (slotsMap*) remove(slot, 1, mustAllocate); if (new_map == NULL) return slotsOop(failedAllocationOop); new_map->slots_length = new_map->slots_length->decrement(); new_map->init_dependents(); mapOop new_moop = new_map->enclosing_mapOop(); new_moop->init_mark(); slotsOop new_obj; switch (slot->type->slot_type()) { case obj_slot_type: assert_smi(slot->data, "data slot contents isn't an offset"); new_obj= obj->is_byteVector() ? (slotsOop) byteVectorOop(obj)->remove(object_size(obj), smiOop(slot->data)->value(), 1, mustAllocate, true) : (slotsOop) slotsOop(obj)->remove(object_size(obj), smiOop(slot->data)->value(), 1, mustAllocate, true); if (oop(new_obj) == failedAllocationOop) return slotsOop(failedAllocationOop); // check-stores done by remove already new_map->shift_obj_slots(smiOop(slot->data), -1); new_map->object_length = new_map->object_length->decrement(); break; case arg_slot_type: { // fix up any arg slots after this one assert_smi(slot->data, "bad arg index"); fint argIndex= smiOop(slot->data)->value(); FOR_EACH_SLOTDESC(new_map, s) { if (s->is_arg_slot()) { assert_smi(s->data, "bad arg index"); fint a= smiOop(s->data)->value(); if (a > argIndex) s->data= as_smiOop(a - 1); } } } // fall through case map_slot_type: new_obj= slotsOop(obj->clone(mustAllocate)); if (oop(new_obj) == failedAllocationOop) return slotsOop(failedAllocationOop); break; default: ShouldNotReachHere(); // unexpected slot type; } new_obj->set_canonical_map(new_map); return new_obj; }
PRIM_DECL_2(doubleByteArrayPrimitives::at, oop receiver, oop index) { PROLOGUE_2("at", receiver, index); ASSERT_RECEIVER; // check index type if (!index->is_smi()) return markSymbol(vmSymbols::first_argument_has_wrong_type()); // check index value if (!doubleByteArrayOop(receiver)->is_within_bounds(smiOop(index)->value())) return markSymbol(vmSymbols::out_of_bounds()); return as_smiOop(doubleByteArrayOop(receiver)->doubleByte_at(smiOop(index)->value())); }
void CodeGen::assignment(Location receiver, realSlotRef* path, Location val, bool isMem) { // <move arg, t> // <loadPath rr, path, receiver> // store receiver/rr, offset - Mem_Tag, arg/t // <check_store> a.Comment("Begin Assignment"); Location t; if (isRegister(val) && val != CReceiverReg) { t = val; } else { t = Temp1; move(t, val); // load argument } assert(t != Temp2, "register conflict"); int32 offset = smiOop(path->desc->data)->byte_count() - Mem_Tag; if (path->holder->is_object_or_map()) { Location t1 = loadPath(CReceiverReg, path->holder, receiver, Temp1); a.StoreI(t1, offset, t); // store object data slot contents if (isMem) { a.AddI(t1, offset, Temp1); // compute store address recordStore(Temp1); } } else { fatal("don't support vframe lookups yet"); } a.Comment("End Assignment"); }
void CodeGen::loadOop(Location dest, Location src_register, slotDesc* s) { Location t = isRegister(dest) ? dest : Temp1; int32 offset = smiOop(s->data)->byte_count() - Mem_Tag; a.LoadI(src_register, offset, t); if (dest != t) move(dest, t); }
void CodeGen::assignment(Location receiver, realSlotRef* path, Location val, bool isMem) { a.Comment("Begin Assignment"); // called from assignmentCode; real assignment method int32 offset = smiOop(path->desc->data)->byte_count() - Mem_Tag; if (path->holder->is_object_or_map()) { Location tmp = val == Temp1 ? Temp2 : Temp1; bool yipes = tmp == receiver; if (yipes) a.pushl(val); Location tr = loadPath(tmp, path->holder, receiver, tmp); a.leal(tr, offset, NumberOperand, tr); Location r; int32 d; OperandType t; Location other_temp = tr == Temp1 ? Temp2 : Temp1; if (yipes) a.popl(other_temp); else if (val != other_temp) { reg_disp_type_of_loc(&r, &d, &t, val); a.movl(r, d, t, other_temp); } a.movl(other_temp, tr, 0, NumberOperand); if (isMem) { recordStore(tr); } } else { fatal("don't support vframe lookups yet"); } a.Comment("End Assignment"); }
void SendNode::gen() { BasicNode::gen(); offset = theAssembler->offset(); assert(bci() != IllegalBCI, "should have legal bci"); genPcDesc(); genBreakpointBeforeCall(); theAssembler->CallB(Memory->code->trapdoors->SendMessage_stub_td()); theAssembler->Nop(); theAssembler->Data(mask()); nlrCode(); theAssembler->Zero(); // nmlns theAssembler->Zero(); if (sel != badOop) { if (isPerformLookupType(l)) { assert_smi(sel, "should be an integer argcount"); theAssembler->Data(smiOop(sel)->value()); // really arg count } else { assert_string(sel, "should be a string constant"); theAssembler->Data(sel); // constant selector } } if ((l & UninlinableSendMask) == 0) theSIC->noInlinableSends = false; theAssembler->Data(l); verifySendInfo(); if (del) { assert(needsDelegatee(l), "shouldn't have a delegatee"); theAssembler->Data(del); } }
Node* NodeGen::testNLR(smi homeID) { // test if NLR has reached home; the node returned is the success // branch (i.e. the home has been reached), current is the other // branch Node* homeIDTest = NULL; if (homeID) { // note: will be 0 if no inlining if (isImmediate(smiOop(homeID))) { APPEND(new ArithRCNode(SubCCArithOp, nlrHomeIDPR, homeID, noPR)); } else { APPEND(new LoadIntNode(homeID, nlrTempPR)); APPEND(new ArithRRNode(SubCCArithOp, nlrHomeIDPR, nlrTempPR, noPR)); } homeIDTest = APPEND(new BranchNode(EQBranchOp)); APPEND1(new ArithRRNode(SubCCArithOp, nlrHomePR, framePR, noPR)); } else { APPEND (new ArithRRNode(SubCCArithOp, nlrHomePR, framePR, noPR)); } Node* homeFrameTest = APPEND(new BranchNode(EQBranchOp)); // home & homeID match Node* finalReturn = new NopNode; APPEND1(finalReturn); // no match, continue NLR Node* cont = new MergeNode("testNLR cont"); if (homeIDTest) homeIDTest->append(cont); homeFrameTest->append(cont); current = cont; return finalReturn; }
Label* CodeGen::SendDesc(RegisterState* s, LookupType lookupType, oop selector, oop delegatee) { a.Comment("begin SendDesc"); Label past_send_desc(a.printing); a.jmp(&past_send_desc); s->genMask(); // mask of used regs Label* l = new Label(a.printing); a.jmp(l); // non-local return code assert((a.offset() & Tag_Mask) == 0, "must be aligned"); a.Zero(); // nmlns a.Zero(); if (selector != badOop) { if (isPerformLookupType(lookupType)) { assert_smi(selector, "should be an integer argcount"); a.Data(smiOop(selector)->value(), true); // really arg count } else { assert_string(selector, "should be a string constant"); a.Data(selector, true); // constant selector } } # ifdef SIC_COMPILER if (theCompiler->containsLoop) { // need counters for the sends to know how often the loop executes a.Data(withCountBits(lookupType, Counting), true); } else { a.Data(lookupType, true); } # else a.Data(lookupType, true); # endif # if GENERATE_DEBUGGING_AIDS if (CheckAssertions) switch (lookupType) { case DirectedResendLookupType: assert(lookupType & DelegateeStaticBit, "should have static delegatee"); assert_string(delegatee, "should be a string"); // fall through case ImplicitSelfLookupType: case ResendLookupType: case StaticNormalLookupType: case NormalLookupType: assert(!isPerformLookupType(lookupType), "should have a static selector"); assert_string(selector, "should be a string"); break; default: break; } # endif if (delegatee != badOop) { assert(needsDelegatee(lookupType), "shouldn't have a delegatee"); a.Data(delegatee, true); } past_send_desc.define(); a.Comment("end SendDesc"); return l; }
void NodeGen::pathLookup(realSlotRef* path, PReg* receiver, PReg* dest) { if (path->holder->is_object_or_map()) { PReg* base = loadPath(path->holder, receiver, dest); fint offset = smiOop(path->desc->data)->byte_count() - Mem_Tag; APPEND(new LoadOffsetNode(base, offset, dest)); } else { fatal("don't support vframe lookups"); } }
oop objVectorOopClass::ov_at_put_prim(oop rcvr, oop indexOop, oop contents) { if (!rcvr->is_objVector()) return ErrorCodes::vmString_prim_error(BADTYPEERROR); if (!indexOop->is_smi()) return ErrorCodes::vmString_prim_error(BADTYPEERROR); smi index = smiOop(indexOop)->value(); if (unsigned(index) >= unsigned(objVectorOop(rcvr)->length())) return ErrorCodes::vmString_prim_error(BADINDEXERROR); objVectorOop(rcvr)->obj_at_put(index, contents); return rcvr; }
void smiMap::print(oop obj) { if (obj->is_map()) { lprintf("smi "); } else { smiOop(obj)->print_oop(); lprintf(": "); } immediateMap::print(obj); }
void CodeGen::loadOop(Location dest, Location src, slotDesc* s) { a.Comment("loadOop1"); int32 offset = smiOop(s->data)->byte_count() - Mem_Tag; Location t = isRegister(src) ? src : dest != Temp1 ? Temp1 : Temp2; Location tt = isRegister(dest) ? dest : src != Temp1 ? Temp1 : Temp2; move(t, src); a.movl(t, offset, NumberOperand, tt); move(dest, tt); }
void slot_info::init(oop node_pt, char* selector) { // Check if node_pt has data_slot selector and save offset in _offset. stringOop sel = Memory->string_table->lookup(selector, strlen(selector)); slotDesc* sd = node_pt->find_slot(sel); if (sd && sd->type->is_obj_slot()) { _offset = smiOop(sd->data)->value(); } else { _offset = invalid_offset; } }
extern "C" oop* setup_deoptimization_and_return_new_sp(oop* old_sp, int* old_fp, objArrayOop frame_array, int* current_frame) { ResourceMark rm; // Save all parameters for later use (check unpack_frame_array) ::old_sp = old_sp; ::old_fp = old_fp; ::frame_array = frame_array; ::cur_fp = current_frame; smiOop number_of_vframes = smiOop(frame_array->obj_at(StackChunkBuilder::number_of_vframes_index)); smiOop number_of_locals = smiOop(frame_array->obj_at(StackChunkBuilder::number_of_locals_index)); assert(number_of_vframes->is_smi(), "must be smi"); assert(number_of_locals->is_smi(), "must be smi"); new_sp = old_sp - frame::interpreter_stack_size(number_of_vframes->value(), number_of_locals->value()); return new_sp; }
PRIM_DECL_3(doubleValueArrayPrimitives::atPut, oop receiver, oop index, oop value) { PROLOGUE_3("atPut", receiver, index, value); ASSERT_RECEIVER; // check index type if (!index->is_smi()) return markSymbol(vmSymbols::first_argument_has_wrong_type()); // check value type if (!value->is_double()) return markSymbol(vmSymbols::second_argument_has_wrong_type()); // check index value if (!doubleValueArrayOop(receiver)->is_within_bounds(smiOop(index)->value())) return markSymbol(vmSymbols::out_of_bounds()); // do the operation doubleValueArrayOop(receiver)->double_at_put(smiOop(index)->value(), doubleOop(value)->value()); return receiver; }
void SICGenHelper::loadImmediateOop(oop p, Location dest, bool isInt) { assert(isRegister(dest), "must be a register"); if (p == 0) { a->OrR(G0, G0, dest); } else if ((isInt || !p->is_mem()) && isImmediate(smiOop(p))) { a->OrI(G0, (int)p, dest); } else { a->SetHiO(p, dest); // load high part of value a->AddO(dest, p, dest); // add low part } }
PRIM_DECL_2(doubleByteArrayPrimitives::characterAt, oop receiver, oop index) { PROLOGUE_2("characterAt", receiver, index); ASSERT_RECEIVER; // check index type if (!index->is_smi()) return markSymbol(vmSymbols::first_argument_has_wrong_type()); // range check if (!doubleByteArrayOop(receiver)->is_within_bounds(smiOop(index)->value())) return markSymbol(vmSymbols::out_of_bounds()); // fetch double byte doubleByte byte = doubleByteArrayOop(receiver)->doubleByte_at(smiOop(index)->value()); if (byte < 256) { // return the byte+1'th element in asciiCharacter return Universe::asciiCharacters()->obj_at(byte+1); } else return markSymbol(vmSymbols::out_of_bounds()); }
void WeakArrayRegister::follow_contents() { for(int index = 0; index < weakArrays->length(); index++) { weakArrayOop w = weakArrays->at(index); int non_indexable_size = nis->at(index); bool encounted_near_death_objects = false; int length = smiOop(w->raw_at(non_indexable_size))->value(); for(int i = 1; i <= length; i++) { MarkSweep::reverse_and_follow(w->oops(non_indexable_size+i)); } } }
void blockOopClass::setScope(frame* newScope) { blockOopClass *b= addr(); frame* f= b->homeFr(); if (NLRSupport::is_bad_home_reference((char*)f)) { // prototype block or non-LIFO block if (newScope != NULL) ShouldNotReachHere(); // shouldn't try to set scope pointer } else { assert_smi(newScope, "should be a word-aligned pointer"); b->setHomeFr(smiOop(newScope)); } }
oop smi_mod_prim(smiOop rcvr, smiOop arg) { if (!rcvr->is_smi()) return ErrorCodes::vmString_prim_error(BADTYPEERROR); if (! arg->is_smi()) return ErrorCodes::vmString_prim_error(BADTYPEERROR); smi r = rcvr->value(); smi a = arg->value(); smi aa = a >= 0 ? a : -a; if (a == 0) return ErrorCodes::vmString_prim_error(DIVISIONBYZEROERROR); int32 res = r % a; assert( smiOop(smi_div_prim(rcvr, arg))->value() * a + res == r, "smi_mod_prim incorrect on this platform"); return as_smiOop(res); }
PRIM_DECL_2(behaviorPrimitives::classVariableAt, oop behavior, oop index) { PROLOGUE_2("classVariableAt", behavior, index); if (!behavior->is_klass()) return markSymbol(vmSymbols::first_argument_has_wrong_type()); if (!index->is_smi()) return markSymbol(vmSymbols::second_argument_has_wrong_type()); int i = smiOop(index)->value(); if (i > 0 && i <= klassOop(behavior)->klass_part()->number_of_classVars()) return klassOop(behavior)->klass_part()->classVar_at(i); return markSymbol(vmSymbols::out_of_bounds()); }
bool CompiledLoop::isIncrement(PReg* p, ArithOpCode op) { // is p a suitable increment (i.e., a positive constant or loop-invariant variable)? _increment = p; if (p->isConstPReg()) { oop c = ((ConstPReg*)p)->constant; if (!c->is_smi()) return false; _isCountingUp = (smiOop(c)->value() > 0) ^ (op == tSubArithOp); return true; } else { // fix this: need to check sign in loop header return defsInLoop(p) == 0; } }
int32* objVectorOopClass::convertIntArray() { oop* src = objs(); oop* end = src + length(); int32* result = NEW_RESOURCE_ARRAY( int32, length()); int32* dst = result; while (src < end) { oop s = *src++; if (!s->is_smi()) return NULL; *dst++ = smiOop(s)->value(); } return result; }
Expr* PrimInliner::smi_Mod(Expr* x, Expr* y) { if (y->preg()->isConstPReg()) { assert(y->is_smi(), "type check should have failed"); int d = smiOop(((ConstPReg*)y->preg())->constant)->value(); if (is_power_of_2(d)) { // replace it with mask ConstPReg* preg = new_ConstPReg(_scope, as_smiOop(d-1)); return smi_BitOp(tAndArithOp, x, new ConstantExpr(preg->constant, preg, _gen->_current)); } } // otherwise leave it alone return NULL; }
void CodeGen::assignment(Location receiver, slotDesc* s, Location val) { // this one called for impl self, arg on stack a.Comment("Begin Simple Assignment"); assert(!isRegister(receiver) && !isRegister(val), "called from genReceiverDataAccess, rcvr is self, val is arg or local, check this so I can use Temp[12]"); move(Temp2, receiver); int32 offset = smiOop(s->data)->byte_count() - Mem_Tag; a.leal(Temp2, offset, NumberOperand, Temp2); // store object data slot contents move(Temp1, val); a.movl(Temp1, Temp2, 0, NumberOperand); // store object data slot contents recordStore(Temp2); // NB: recordStore will clobber Temp2 till I put in ByteMapBaseReg a.Comment("End Simple Assignment"); }