void GSDrawScanlineCodeGenerator::alltrue() { #if _M_SSE >= 0x500 vpmovmskb(eax, xmm7); cmp(eax, 0xffff); je("step", T_NEAR); #else pmovmskb(eax, xmm7); cmp(eax, 0xffff); je("step", T_NEAR); #endif }
void JavaApplication::handleException( JNIEnv* env, Exceptions& e ) const { jthrowable exception = env->ExceptionOccurred(); if ( exception ) { JVMObject je(exception); if ( e.doNotSend.IsInstanceOf( exception ) ) { env->ExceptionClear(); throw FIX::DoNotSend(); } else if ( e.rejectLogon.IsInstanceOf( exception ) ) { env->ExceptionClear(); throw FIX::RejectLogon(); } else if ( e.unsupportedMessageType.IsInstanceOf( exception ) ) { env->ExceptionClear(); throw FIX::UnsupportedMessageType(); } else if ( e.fieldNotFound.IsInstanceOf( exception ) ) { env->ExceptionClear(); throw FIX::FieldNotFound( je.getInt("field") ); } else if ( e.incorrectTagValue.IsInstanceOf( exception ) ) { env->ExceptionClear(); throw FIX::IncorrectTagValue( je.getInt("field") ); } else if ( e.incorrectDataFormat.IsInstanceOf( exception ) ) { env->ExceptionClear(); throw FIX::IncorrectDataFormat( je.getInt("field") ); } else { env->ExceptionDescribe(); env->ExceptionClear(); exit(1); } } }
void JitFragmentWriter::_emitRecordType(RewriterVar* type_recorder_var, RewriterVar* obj_cls_var) { // This directly emits the instructions of the recordType() function. assembler::Register obj_cls_reg = obj_cls_var->getInReg(); assembler::Register type_recorder_reg = type_recorder_var->getInReg(Location::any(), true, obj_cls_reg); assembler::Indirect last_seen_count = assembler::Indirect(type_recorder_reg, offsetof(TypeRecorder, last_count)); assembler::Indirect last_seen_indirect = assembler::Indirect(type_recorder_reg, offsetof(TypeRecorder, last_seen)); assembler->cmp(last_seen_indirect, obj_cls_reg); { assembler::ForwardJump je(*assembler, assembler::COND_EQUAL); assembler->mov(obj_cls_reg, last_seen_indirect); assembler->movq(assembler::Immediate(0ul), last_seen_count); } assembler->incl(last_seen_count); type_recorder_var->bumpUse(); obj_cls_var->bumpUse(); }
void JitFragmentWriter::_emitOSRPoint(RewriterVar* result, RewriterVar* node_var) { RewriterVar::SmallVector args; args.push_back(getInterp()); args.push_back(node_var); _call(result, false, (void*)ASTInterpreterJitInterface::doOSRHelper, args, RewriterVar::SmallVector()); auto result_reg = result->getInReg(assembler::RDX); result->bumpUse(); assembler->test(result_reg, result_reg); { assembler::ForwardJump je(*assembler, assembler::COND_EQUAL); assembler->mov(assembler::Immediate(0ul), assembler::RAX); // TODO: use xor assembler->add(assembler::Immediate(JitCodeBlock::sp_adjustment), assembler::RSP); assembler->pop(assembler::R12); assembler->pop(assembler::R14); assembler->retq(); } assertConsistent(); }
void GSDrawScanlineCodeGenerator::WritePixel(const Xmm& src, const Reg64& addr, const Reg8& mask, bool fast, int psm, int fz) { if(fast) { // if(fzm & 0x0f) GSVector4i::storel(&vm16[addr + 0], fs); // if(fzm & 0xf0) GSVector4i::storeh(&vm16[addr + 8], fs); test(mask, 0x0f); je("@f"); vmovq(qword[r13 + addr * 2], src); L("@@"); test(mask, 0xf0); je("@f"); vmovhps(qword[r13 + addr * 2 + 8 * 2], src); L("@@"); // vmaskmovps? } else { // if(fzm & 0x03) WritePixel(fpsm, &vm16[addr + 0], fs.extract32<0>()); // if(fzm & 0x0c) WritePixel(fpsm, &vm16[addr + 2], fs.extract32<1>()); // if(fzm & 0x30) WritePixel(fpsm, &vm16[addr + 8], fs.extract32<2>()); // if(fzm & 0xc0) WritePixel(fpsm, &vm16[addr + 10], fs.extract32<3>()); test(mask, 0x03); je("@f"); WritePixel(src, addr, 0, psm); L("@@"); test(mask, 0x0c); je("@f"); WritePixel(src, addr, 1, psm); L("@@"); test(mask, 0x30); je("@f"); WritePixel(src, addr, 2, psm); L("@@"); test(mask, 0xc0); je("@f"); WritePixel(src, addr, 3, psm); L("@@"); } }
void JavaMessageStore::handleException( JNIEnv* env, Exceptions& e ) const { jthrowable exception = env->ExceptionOccurred(); if ( exception ) { if ( e.ioException.IsInstanceOf( exception ) ) { env->ExceptionClear(); JVMObject je(exception); jstring reason = je.callStringMethod("getMessage"); const char* ureason = env->GetStringUTFChars( reason, 0 ); FIX::IOException cppException( ureason ); env->ReleaseStringUTFChars( reason, ureason ); env->DeleteLocalRef( reason ); throw cppException; } else { env->ExceptionDescribe(); env->ExceptionClear(); exit(1); } } }
job* job_receiver::receive(const std::string& filename) { try { parser->parse(filename.c_str()); } catch(const XERCES_CPP_NAMESPACE_QUALIFIER XMLException& toCatch) { char* message = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(toCatch.getMessage()); job_exception je(std::string("XML error: ")+message); XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&message); throw je; } catch(const XERCES_CPP_NAMESPACE_QUALIFIER DOMException& toCatch) { char* message = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(toCatch.msg); job_exception je(std::string("XML DOM error: ")+message); XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&message); throw je; } catch(const XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException& toCatch) { // more verbose for parser errors char* message = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(toCatch.getMessage()); job_exception je(std::string("XML SAX Parser error: ")+message); char location[100]; snprintf(location,sizeof(location),", line %ld column %ld",toCatch.getLineNumber(),toCatch.getColumnNumber()); je.append(location); XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&message); throw je; } catch(const XERCES_CPP_NAMESPACE_QUALIFIER SAXException& toCatch) { char* message = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(toCatch.getMessage()); job_exception je(std::string("XML SAX error: ")+message); XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&message); throw je; } // extract root element, root attributes and root name XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* doc=parser->getDocument(); if (doc==NULL) throw job_exception("xml job document not found"); XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* rootelement=doc->getDocumentElement(); if (rootelement==NULL) throw job_exception("xml job root document not found"); char* docname=XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(rootelement->getNodeName()); XERCES_CPP_NAMESPACE_QUALIFIER DOMNamedNodeMap* rootattrs=rootelement->getAttributes(); // check the job number XMLCh* docnoname=XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode("no"); XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* jobno_attr=rootattrs->getNamedItem(docnoname); XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&docnoname); if (jobno_attr==NULL) { docnoname=XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode("no"); jobno_attr=rootattrs->getNamedItem(docnoname); XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&docnoname); } size_t no=0; if (jobno_attr==NULL) fprintf(stderr,"Warning: job %" SIZETPRINTFLETTER ": root element has no job number\n",no); else { char* docno=XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(jobno_attr->getNodeValue()); no=strtoul(docno,NULL,0); XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&docno); } job* this_job=NULL; // determine the job type by name if (strcasecmp(docname,"quit")==0) { this_job=new quit_job(no); } else if (strcasecmp(docname,"nop")==0) { this_job=new do_nothing_job(no); } else if (strcasecmp(docname,"pause")==0) { this_job=new pause_job(no); } /* pause */ else if (strcasecmp(docname,"restart")==0) { this_job=new restart_job(no); } /* restart */ else if (strcasecmp(docname,"wait")==0) { this_job=new wait_job(no,rootattrs); } /* wait */ else if (strcasecmp(docname,"experiment")==0) { try { this_job=new experiment(no, rootelement); } catch (const XERCES_CPP_NAMESPACE_QUALIFIER DOMException& de) { char* domerrmsg=XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(de.msg); char domerrno[5]; snprintf(domerrno,5,"%d",de.code); job_exception je("sorry, something happend while parsing experiment job: "); je.append(domerrmsg); je.append(", code "); je.append(domerrno); XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&domerrmsg); // cleanup missing throw je; } } else if (strcasecmp(docname,"configuration")==0) { try { this_job=new configuration(no, rootelement); } catch (const XERCES_CPP_NAMESPACE_QUALIFIER DOMException& de) { char* domerrmsg=XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(de.msg); char domerrno[5]; snprintf(domerrno,5,"%d",de.code); job_exception je("sorry, something happend while parsing configuration job: "); je.append(domerrmsg); je.append(", code "); je.append(domerrno); XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&domerrmsg); // cleanup missing throw je; } } XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&docname); parser->reset(); parser->resetDocument(); parser->resetDocumentPool(); return this_job; }
void GPUDrawScanlineCodeGenerator::alltrue() { pmovmskb(eax, xmm7); cmp(eax, 0xffff); je("step", T_NEAR); }
push my_perl, call near offset $PL_op->op_ppaddr */ T_CHARARR x86thr_call[] = { 0x89,0x1c,0x24, /* mov %ebx,(%esp) */ 0xE8 /* call near offset */ }; /* after each call: PL_op = eax. PL_op is at my_perl->Iop, so update it for threading concurrency. */ T_CHARARR x86thr_save_plop[] = { 0x89,0x43,0x04 /* mov %eax,0x4(%ebx) */ }; /* save new PL_op into my_perl */ T_CHARARR x86_nop[] = {0x90}; /* pad */ T_CHARARR x86thr_dispatch[] = { mov_4ebp_edx, /* value of PL_sig_pending from 4(%ebp) (ptr) to %eax */ mov_redx_eax, test_eax_eax, je(8) /* je +8 */ }; /* call Perl_despatch_signals */ T_CHARARR maybranch_plop[] = { mov_mem_rebp8,fourbyte }; CODE * push_maybranch_plop(CODE *code, OP* next) { CODE maybranch_plop[] = { mov_mem_rebp8}; PUSHc(maybranch_plop); PUSHrel(&next); return code; } T_CHARARR maybranch_check[] = { cmp_eax_rebp8,
void vframe::print_xml_on(JavaThread *thread, xmlBuffer *xb) const { ResourceMark rm; frame fr = get_frame(); const char *frame_style = "UNKNOWN"; CodeBlob*cb=CodeCache::find_blob(fr.pc()); if( fr.is_interpreted_frame() ) frame_style = "INTERPRETER"; else if( cb && cb->is_native_method() ) frame_style = "NATIVE"; else if( cb && cb->is_c1_method() ) frame_style = "COMPILER1"; else if( cb && cb->is_c2_method() ) frame_style = "COMPILER2"; // Frame header xb->name_value_item("frame_style",frame_style); // Java Locals if (!fr.is_java_frame()) return; // no more printing to be done const methodOop moop = method(); if (moop->is_native()) return; // no more printing to be done const int max_locals = moop->max_locals(); if(fr.is_compiled_frame()){ for( int i=0; i<max_locals; i++ ) { xmlElement je(xb, "java_element"); { xmlElement n(xb, "name", xmlElement::delayed_LF); bool out_of_scope = true; const char* name = moop->localvariable_name(i, bci(), out_of_scope); if( name ) xb->print("%s%s%s", out_of_scope ? "{": "", name, out_of_scope ? "}": ""); else xb->print("JL%-2d", i); } DebugScopeValue::Name vreg = _ds->get_local(i); if( !DebugScopeValue::is_valid(vreg) ) { xb->name_value_item("type","invalid"); xb->name_ptr_item("value",0); } else { intptr_t *data_ptr = fr.reg_to_addr(DebugScopeValue::to_vreg(vreg)); const int rel_pc = cb->rel_pc(fr.pc()); const bool isoop = cb->oop_maps()->is_oop( rel_pc, VReg::as_VOopReg(DebugScopeValue::to_vreg(vreg)) ); if( isoop ) { xb->name_value_item("type", "oop"); oop o = ((objectRef*)data_ptr)->as_oop(); o->print_xml_on(xb, true); } else { xb->name_value_item("type", "normal"); xb->name_ptr_item("value", (void*)*data_ptr); } } } }else if(fr.is_interpreted_frame()){ for( int i = 0; i < max_locals; i++ ) { frame::InterpreterStackSlotType tag = fr.tag_at_address(fr.interpreter_frame_local_addr(i)); if (tag == frame::double_slot_primitive_type) i++;//skip the tag slot xmlElement je(xb, "java_element"); { xmlElement n(xb, "name", xmlElement::delayed_LF); bool out_of_scope = true; const char* name = moop->localvariable_name(i, bci(), out_of_scope); if (name != NULL) { xb->print("%s%s%s", out_of_scope ? "{": "", name, out_of_scope ? "}": ""); } else { xb->print("JL%-2d", i); } } intptr_t local_value = fr.interpreter_frame_local_at(i); switch (tag) { case frame::single_slot_primitive_type: { xb->name_value_item("type", "single_slot_primitive_type"); xb->name_ptr_item("value", (void*)local_value); break; } case frame::double_slot_primitive_type: { xb->name_value_item("type", "double_slot_primitive_type"); xb->name_ptr_item("value", (void*)local_value); break; } case frame::single_slot_ref_type: { xb->name_value_item("type", "oop"); oop o = objectRef((uint64_t)local_value).as_oop(); o->print_xml_on(xb, true); break; } default: ShouldNotReachHere(); break; } } } }
void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID) { int dst = instruction[1].u.operand; int callee = instruction[2].u.operand; int argCount = instruction[3].u.operand; int registerOffset = instruction[4].u.operand; linkSlowCase(iter); // The arguments have been set up on the hot path for op_call_eval if (opcodeID == op_call) compileOpCallSetupArgs(instruction); else if (opcodeID == op_construct) compileOpConstructSetupArgs(instruction); // Fast check for JS function. __ testl_i32r(JSImmediate::TagMask, X86::ecx); JmpSrc callLinkFailNotObject = __ jne(); __ cmpl_im(reinterpret_cast<unsigned>(m_interpreter->m_jsFunctionVptr), 0, X86::ecx); JmpSrc callLinkFailNotJSFunction = __ jne(); // First, in the case of a construct, allocate the new object. if (opcodeID == op_construct) { emitCTICall(Interpreter::cti_op_construct_JSConstruct); emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount); emitGetVirtualRegister(callee, X86::ecx); } __ movl_i32r(argCount, X86::edx); // Speculatively roll the callframe, assuming argCount will match the arity. __ movl_rm(X86::edi, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)), X86::edi); __ addl_ir(registerOffset * static_cast<int>(sizeof(Register)), X86::edi); m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_interpreter->m_ctiVirtualCallPreLink); JmpSrc storeResultForFirstRun = __ jmp(); // This is the address for the cold path *after* the first run (which tries to link the call). m_callStructureStubCompilationInfo[callLinkInfoIndex].coldPathOther = __ label(); // The arguments have been set up on the hot path for op_call_eval if (opcodeID == op_call) compileOpCallSetupArgs(instruction); else if (opcodeID == op_construct) compileOpConstructSetupArgs(instruction); // Check for JSFunctions. __ testl_i32r(JSImmediate::TagMask, X86::ecx); JmpSrc isNotObject = __ jne(); __ cmpl_im(reinterpret_cast<unsigned>(m_interpreter->m_jsFunctionVptr), 0, X86::ecx); JmpSrc isJSFunction = __ je(); // This handles host functions JmpDst notJSFunctionlabel = __ label(); __ link(isNotObject, notJSFunctionlabel); __ link(callLinkFailNotObject, notJSFunctionlabel); __ link(callLinkFailNotJSFunction, notJSFunctionlabel); emitCTICall(((opcodeID == op_construct) ? Interpreter::cti_op_construct_NotJSConstruct : Interpreter::cti_op_call_NotJSFunction)); JmpSrc wasNotJSFunction = __ jmp(); // Next, handle JSFunctions... __ link(isJSFunction, __ label()); // First, in the case of a construct, allocate the new object. if (opcodeID == op_construct) { emitCTICall(Interpreter::cti_op_construct_JSConstruct); emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount); emitGetVirtualRegister(callee, X86::ecx); } // Speculatively roll the callframe, assuming argCount will match the arity. __ movl_rm(X86::edi, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)), X86::edi); __ addl_ir(registerOffset * static_cast<int>(sizeof(Register)), X86::edi); __ movl_i32r(argCount, X86::edx); emitNakedCall(m_interpreter->m_ctiVirtualCall); // Put the return value in dst. In the interpreter, op_ret does this. JmpDst storeResult = __ label(); __ link(wasNotJSFunction, storeResult); __ link(storeResultForFirstRun, storeResult); emitPutVirtualRegister(dst); #if ENABLE(CODEBLOCK_SAMPLING) __ movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), m_interpreter->sampler()->codeBlockSlot()); #endif }
void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, void* returnAddress) { Vector<JmpSrc, 16> failureCases; // Check eax is an object of the right Structure. __ testl_i32r(JSImmediate::TagMask, X86::eax); failureCases.append(__ jne()); __ cmpl_im(reinterpret_cast<uint32_t>(oldStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax); failureCases.append(__ jne()); Vector<JmpSrc> successCases; // ecx = baseObject __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx); // proto(ecx) = baseObject->structure()->prototype() __ cmpl_im(ObjectType, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type), X86::ecx); failureCases.append(__ jne()); __ movl_mr(FIELD_OFFSET(Structure, m_prototype), X86::ecx, X86::ecx); // ecx = baseObject->m_structure for (RefPtr<Structure>* it = chain->head(); *it; ++it) { // null check the prototype __ cmpl_ir(asInteger(jsNull()), X86::ecx); successCases.append(__ je()); // Check the structure id __ cmpl_im(reinterpret_cast<uint32_t>(it->get()), FIELD_OFFSET(JSCell, m_structure), X86::ecx); failureCases.append(__ jne()); __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::ecx, X86::ecx); __ cmpl_im(ObjectType, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type), X86::ecx); failureCases.append(__ jne()); __ movl_mr(FIELD_OFFSET(Structure, m_prototype), X86::ecx, X86::ecx); } failureCases.append(__ jne()); for (unsigned i = 0; i < successCases.size(); ++i) __ link(successCases[i], __ label()); JmpSrc callTarget; // emit a call only if storage realloc is needed if (transitionWillNeedStorageRealloc(oldStructure, newStructure)) { __ push_r(X86::edx); __ push_i32(newStructure->propertyStorageCapacity()); __ push_i32(oldStructure->propertyStorageCapacity()); __ push_r(X86::eax); callTarget = __ call(); __ addl_ir(3 * sizeof(void*), X86::esp); __ pop_r(X86::edx); } // Assumes m_refCount can be decremented easily, refcount decrement is safe as // codeblock should ensure oldStructure->m_refCount > 0 __ subl_im(1, reinterpret_cast<void*>(oldStructure)); __ addl_im(1, reinterpret_cast<void*>(newStructure)); __ movl_i32m(reinterpret_cast<uint32_t>(newStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax); // write the value __ movl_mr(FIELD_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax); __ movl_rm(X86::edx, cachedOffset * sizeof(JSValue*), X86::eax); __ ret(); JmpSrc failureJump; if (failureCases.size()) { for (unsigned i = 0; i < failureCases.size(); ++i) __ link(failureCases[i], __ label()); restoreArgumentReferenceForTrampoline(); failureJump = __ jmp(); } void* code = __ executableCopy(m_codeBlock->executablePool()); if (failureCases.size()) X86Assembler::link(code, failureJump, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail)); if (transitionWillNeedStorageRealloc(oldStructure, newStructure)) X86Assembler::link(code, callTarget, reinterpret_cast<void*>(resizePropertyStorage)); stubInfo->stubRoutine = code; ctiRepatchCallByReturnAddress(returnAddress, code); }
SystemPath SystemPath::toRelative( SystemPath const& aBaseSystemPath ) const { // 1. "" (empty) means Model itself, which is invalid for this method. // 2. Not absolute is invalid (not absolute implies not empty). if( ! isAbsolute() || isModel() ) { return *this; } if( ! aBaseSystemPath.isAbsolute() || aBaseSystemPath.isModel() ) { THROW_EXCEPTION( BadSystemPath, "[" + aBaseSystemPath.asString() + "] is not an absolute SystemPath" ); } SystemPath aThisPathCopy; SystemPath const* thisPath; if ( !isCanonicalized() ) { aThisPathCopy = *this; aThisPathCopy.canonicalize(); thisPath = &aThisPathCopy; } else { thisPath = this; } SystemPath aBaseSystemPathCopy; SystemPath const* aCanonicalizedBaseSystemPath; if ( !aBaseSystemPath.isCanonicalized() ) { aCanonicalizedBaseSystemPath = &aBaseSystemPath; } else { aBaseSystemPathCopy = aBaseSystemPath; aBaseSystemPathCopy.canonicalize(); aCanonicalizedBaseSystemPath = &aBaseSystemPathCopy; } SystemPath aRetval; StringVector::const_iterator j( thisPath->theComponents.begin() ), je( thisPath->theComponents.end() ); StringVector::const_iterator i( aCanonicalizedBaseSystemPath->theComponents.begin() ), ie( aCanonicalizedBaseSystemPath->theComponents.end() ); while ( i != ie && j != je ) { String const& aComp( *i ); if ( aComp != *j ) { break; } ++i, ++j; } if ( i != ie ) { while ( i != ie ) { aRetval.theComponents.push_back( ".." ); ++i; } } std::copy( j, je, std::back_inserter( aRetval.theComponents ) ); if ( aRetval.theComponents.empty() ) { aRetval.theComponents.push_back( "." ); } return aRetval; }