void stringTable::add(stringOop s) { assert(s->is_string(), "adding something that's not a string to the string table"); assert(s->is_old(), "all strings should be tenured"); int32 hashValue = hash(s->bytes(), s->length()); basic_add(s, hashValue); }
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); }
oop slotsMap::copy_add_data_slot(slotsOop obj, stringOop name, slotType type, oop contents, oop anno, bool mustAllocate) { if (!name->is_unary()) { return ErrorCodes::vmString_prim_error(SLOTNAMEERROR); } slotDesc* old = find_slot(name); if (!old) return copy_add_new_slot(obj, name, type, contents, anno, mustAllocate); if (old->is_obj_slot()) // change in place; if type is map_slot, just changes value return (slotsOop)change_slot(obj, old, OBJ_SLOT(type), contents, anno, mustAllocate); // remove then add obj slot slotsOop result= copy_remove_one_slot(obj, old, mustAllocate); if (oop(result) == failedAllocationOop) return result; slotsMap *new_map= (slotsMap*)result->map(); return new_map->copy_add_new_slot(result, name, type, contents, anno, mustAllocate); }
void methodAppraiser::do_send_code( bool isSelfImplicit, stringOop sel, fint argc) { if (!isSelfImplicit) ++argc; // Explicit receiver bool penaltyFlag = false; for (fint argnum = 0; argnum < argc; argnum++) { penaltyFlag |= penaltyStack.pop(); } if (sel->is_prim_name()) { // a primitive; don't count the previous fail block in total length cost -= failLen; cost += cp->primCallCost; } else if (isCheapMessage(sel)) { cost += cp->cheapSendCost; } else if (!UseLocalAccessBytecodes && isSelfImplicit && !( is.is_undirected_resend || is.delegatee ) && checkLocalSlot(sel, isLocal)) { // a local slot access cost += cp->localSendCost; } else { cost += isSelfImplicit ? cp->selfSendCost : cp->unknownSendCost; if (penaltyFlag) cost += cp->blockArgPenalty; } failLen = 0; penaltyStack.push(false); // penalties already taken into account }
void AbstractByteCode::GenSendByteCode( fint offset, fint length, stringOop selector, bool isSelfImplicit, bool isUndirectedResend, stringOop resendTarget) { if (resendTarget != NULL) { GenDelegateeByteCode(offset, length, resendTarget); } else if ( isUndirectedResend ) GenUndirectedResendByteCode(offset, length); fint argc = selector->arg_count(); if (GenArgCountBytecode && argc != 0) GenCode(offset, length, BuildCode( ARGUMENT_COUNT_CODE, GenIndex(offset, length, argc))); GenCode(offset, length, BuildCode( isSelfImplicit ? IMPLICIT_SEND_CODE : SEND_CODE, GenIndex(offset, length, GenLiteral(selector)))); if (!isSelfImplicit) --stack_depth; stack_depth -= argc; assert(stack_depth >= 0, "negative stack?"); ++stack_depth; }
void SCodeScope::memoizeBlocks(stringOop sel) { // memoize block args so they aren't created for inlined cases fint top = exprStack->length(); fint argc = sel->arg_count(); for (fint i = 1; i <= argc; i++) { PReg* r = exprStack->nth(top - i)->preg(); if (r->isBlockPReg()) ((BlockPReg*)r)->memoize(); } }
oop vframeMap::mirror_contents_at(oop obj, stringOop name) { TEST; slotDesc* sd = vfo->method()->find_nonVM_slot(name); if (sd == NULL) return ErrorCodes::vmString_prim_error(SLOTNAMEERROR); if (sd->is_obj_slot() && name->is_1arg_keyword()) return Memory->assignmentMirrorObj; abstract_vframe* vf = vfo->as_vframe(); oop contents = vf->get_slot(sd); return contents->as_mirror(); }
oop processOopClass::NewProcess_prim(smi stackSize, oop rcvr, stringOop sel, objVectorOop args, void *FH) { ResourceMark rm; char *selector = sel->copy_null_terminated(); if (stackSize <= 0 || str_arg_count(selector) > args->length()) { prim_failure(FH, PRIMITIVEFAILEDERROR); return NULL; } Process* p; p = new Process(this, stackSize, rcvr, sel, args); return p->processObj(); }
oop slotsMap::copy_add_assignment_slot(slotsOop obj, stringOop name, slotType type, oop annoIgnored, bool mustAllocate) { Unused(annoIgnored); Unused(type); if (!name->is_1arg_keyword()) return ErrorCodes::vmString_prim_error(ARGUMENTCOUNTERROR); assert(obj->is_slots() && this == obj->map(), "insecurity"); // find the data slot slotDesc* ds= find_assignee_slot(name); if (ds == NULL) return ErrorCodes::vmString_prim_error(LONELYASSIGNMENTSLOTERROR); if (ds->is_obj_slot()) // slot already exists -- nothing to do return obj->clone(mustAllocate); // must be a map slot if (!NakedMethods && ds->data->is_method_like()) return ErrorCodes::vmString_prim_error(UNASSIGNABLESLOTERROR); // remove old map data slot slotsOop result= copy_remove_one_slot(obj, ds, mustAllocate); if (oop(result) == failedAllocationOop) return failedAllocationOop; slotsMap *new_map= (slotsMap*)result->map(); // remove any existing method by same name slotDesc* old= new_map->find_slot(name); if (old) { result= new_map->copy_remove_one_slot(result, old, mustAllocate); if (oop(result) == failedAllocationOop) return result; new_map= (slotsMap*)result->map(); assert(result->is_slots(), "just checking"); } else { result= obj; } // Add in obj slot - enlarge object and put data into it from map result= new_map->copy_add_new_slot(result, ds->name, OBJ_SLOT(ds->type), ds->data, ds->annotation, mustAllocate); if (oop(result) == failedAllocationOop) return failedAllocationOop; assert(result->is_slots(), "should not fail"); return result; }
oop slotsMap::copy_add_method_slot( slotsOop obj, stringOop name, slotType type, oop contents, oop anno, bool mustAllocate) { if (type->is_vm_slot()) { // skip all the checks and do not try to remove it, since // vm slots do not change from obj to map, and rm will fetch anyway slotDesc* sd = obj->find_slot(name); return sd != NULL ? change_slot (obj, sd, type, contents, anno, mustAllocate) : copy_add_new_slot(obj, name, type, contents, anno, mustAllocate); } if ( contents->arg_count() != name->arg_count() ) return ErrorCodes::vmString_prim_error(ARGUMENTCOUNTERROR); if (obj->is_method_like()) return ErrorCodes::vmString_prim_error(BADTYPEERROR); // cannot add methods to methods slotDesc *old= find_slot(name); if (old && old->is_map_slot()) // change in situ return change_slot(obj, old, type, contents, anno, mustAllocate); slotsOop result; if (old) { // remove the old slot, then add in a new one result= (slotsOop)copy_remove_one_slot(obj, old, mustAllocate); if (oop(result) == failedAllocationOop) return failedAllocationOop; if (old->is_assignment_slot_name(name)) { // replace the data slot as a map slot result= ((slotsMap*)result->map())-> copy_add_new_slot(result, old->name, MAP_SLOT(old->type), obj->get_slot(old), old->annotation, mustAllocate); if (oop(result) == failedAllocationOop) return failedAllocationOop; } } else result= obj; return ((slotsMap*)result->map())-> copy_add_new_slot(result, name, MAP_SLOT(type), contents, anno, mustAllocate); }
stringOop stringTable::basic_add(stringOop s, int32 hashValue) { assert(s->is_string(), "adding something that's not a string to the string table"); assert(s->is_old(), "all strings should be tenured"); // Canonical strings must have a hash value (for _IdentityHash) that // is a pure function of the chars in the string. Otherwise, their // hash value would change when they are discarded by a GC and re- // created later. assert(s->mark()->hash() == no_hash, "should not have a hash yet"); s->set_mark(s->mark()->set_hash(hashValue)); assert(s->mark()->hash() != no_hash, "should have a hash now"); stringTableEntry* bucket = bucketFor(hashValue); stringTableLink* old_link; if (bucket->is_string()) { old_link = Memory->string_table->new_link(bucket->get_string()); } else { old_link = bucket->get_link(); } bucket->set_link(Memory->string_table->new_link(s, old_link)); return s; }