int main ( int argc , char** argv ) { int mtrx [ RW ][ CL ] , i , j , m , i1 , j1 , s , c ; int rslt [ CL ] ; int* rsli , * rslj , rsi , rsj ; rsi = rsj = 0 ; // copy matrix for ( i = 0 ; i < RW ; i++ ) for ( j = 0 ; j < CL ; j++ ) mtrx [ i ][ j ] = matrix [ i ][ j ] ; // print init matrix printf ( "Init\n" ) ; pmtr ( mtrx , RW , CL ) ; printf ( "\n\n" ) ; // Step 1. Find minimal elem in row and // vichitaem from all elements of this row l5: s = 1 ; for ( i = 0 ; i < RW ; i++ ) { m = rmin ( mtrx , i , CL ) ; for ( j = 0 ; j < CL ; j++ ) mtrx [ i ][ j ] -= m ; } #if ( DBG == 1 ) // print matrix printf ( "Step 1\n" ) ; pmtr ( mtrx , RW , CL ) ; printf ( "\n\n" ) ; #endif l0: for ( j = 0 ; j < CL ; j++ ) rslt [ j ] = -1 ; // build result array for ( j = 0 ; j < CL ; j++ ) { for ( i = 0 ; i < RW ; i++ ) { if ( ( mtrx [ i ][ j ] == 0 ) && ( rslt [ j ] == -1 ) && ( inar ( rslt , i , CL ) == -1 ) ) { j1 = inrw ( mtrx , i , 0 , j , CL ) ; if ( j1 == -1 ) { rslt [ j ] = i ; break ; } if ( incl ( mtrx , j , 0 , i , RW ) == -1 ) { rslt [ j ] = i ; break; } l1: if ( incl ( mtrx , j1 , 0 , i , RW ) == -1 ) { rslt [ j1 ] = i ; break; } j1 = inrw ( mtrx , i , 0 , j1 , CL ) ; if ( j1 == -1 ) { rslt [ j ] = i ; break; } goto l1 ; } } } // check if task solved j1 = inar ( rslt , -1 , CL ) ; if ( j1 == -1 ) goto l99 ; else if ( s == 2 ) goto l2 ; // Step 2. Use step for columns. s++ ; for ( j = j1 ; j < CL ; j++ ) { if ( rslt [ j ] != -1 ) continue ; m = cmin ( mtrx , j , RW ) ; for ( i = 0 ; i < RW ; i++ ) mtrx [ i ][ j ] -= m ; } #if ( DBG == 1 ) printf ( "Step 2\n" ) ; pmtr ( mtrx , RW , CL ) ; printf ( "\n\n" ) ; #endif goto l0; l2: // Step 3. Find unused rows c = 0 ; for ( i = 0 ; i < RW ; i++ ) if ( inar ( rslt , i , CL ) == -1 ) { rsi++ ; c++ ; if ( ( rsi - 1 ) == 0 ) { rsli = ( int* ) malloc ( rsi * sizeof ( *rsli ) ) ; *rsli = i ; } else { rsli = realloc ( rsli , rsi * sizeof ( *rsli ) ) ; *( rsli + ( rsi - 1 ) ) = i ; } } if ( c == 0 ) goto l4 ; l3: // in all unused rows find columns' numbers with zero c = 0 ; for ( i = 0 ; i < rsi ; i++ ) { j1 = inrw ( mtrx , *( rsli + i ) , 0 , -1 , CL ) ; while ( j1 != -1 ) { if ( !inpn ( rslj , j1 , rsj ) ) { rsj++ ; c++ ; if ( ( rsj - 1 ) == 0 ) { rslj = ( int* ) malloc ( rsj * sizeof ( *rslj ) ) ; *rslj = j1 ; } else { rslj = realloc ( rslj , rsj * sizeof ( *rslj ) ) ; *( rslj + ( rsj - 1 ) ) = j1 ; } } j1 = inrw ( mtrx , *( rsli + i ) , 0 , j1 , CL ) ; } } if ( c == 0 ) goto l4 ; // in all unused columns find rows' numbers with zero c = 0 ; for ( j = 0 ; j < rsj ; j++ ) { i1 = incl ( mtrx , *( rslj + j ) , 0 , -1 , RW ) ; while ( i1 != -1 ) { if ( !inpn ( rsli , i1 , rsi ) ) { rsi++ ; c++ ; rsli = realloc ( rsli , rsi * sizeof ( *rsli ) ) ; *( rsli + ( rsi - 1 ) ) = i1 ; } i1 = incl ( mtrx , *( rslj + j ) , 0 , i1 , RW ) ; } } if ( c ) goto l3 ; l4: // Step 4. Vicherkivaem otmechennie stolbci // i neotmechennie stroki // for i == rsli , j != rslj m = -1 ; for ( i = 0 ; i < RW ; i++ ) { if ( !inpn ( rsli , i , rsi ) ) continue ; for ( j = 0 ; j < CL ; j++ ) { if ( inpn ( rslj , j , rsj ) ) continue ; m = ( mtrx [ i ][ j ] < m || m < 0 ) ? mtrx [ i ][ j ] : m ; } } for ( i = 0 ; i < RW ; i++ ) { for ( j = 0 ; j < CL ; j++ ) { if ( inpn ( rsli , i , rsi ) && !inpn ( rslj , j , rsj ) ) mtrx [ i ][ j ] -= m ; if ( !inpn ( rsli , i , rsi ) && inpn ( rslj , j , rsj ) ) mtrx [ i ][ j ] += m ; } } free ( rsli ) ; free ( rslj ) ; rsi = rsj = 0 ; #if ( DBG == 1 ) printf ( "Step 4\n" ) ; pmtr ( mtrx , RW , CL ) ; printf ( "\n\n" ) ; #endif goto l5 ; l99: for ( j = 0 ; j < CL ; j++ ) printf ( "For task: %d use worker:%d\n" , j , rslt [ j ] ) ; printf ( "\n" ) ; return 0 ; }
void NativeGenerator::generate_native_string_entries() { comment_section("Native entry points for string functions"); { //--------------------java.lang.String.indexof0--------------------------- rom_linkable_entry("native_string_indexof0_entry"); wtk_profile_quick_call(/* param_size*/ 2); comment("Pop the return address"); popl(edi); comment("Push zero for fromIndex"); pushl(Constant(0)); comment("Push back the return address"); pushl(edi); jmp(Constant("native_string_indexof_entry")); rom_linkable_entry_end(); // native_string_indexof0_entry //--------------------java.lang.String.indexof--------------------------- rom_linkable_entry("native_string_indexof_entry"); Label cont, loop, test, failure, success; wtk_profile_quick_call(/* param_size*/ 3); comment("Pop the return address"); popl(edi); comment("Pop the argument: fromIndex"); pop_int(eax, eax); comment("Pop the argument: ch"); pop_int(ebx, ebx); comment("Pop the receiver"); pop_obj(ecx, ecx); cmpl(ebx, Constant(0xFFFF)); jcc(greater, Constant(failure)); cmpl(eax, Constant(0)); jcc(greater_equal, Constant(cont)); movl(eax, Constant(0)); bind(cont); movl(esi, Address(ecx, Constant(String::count_offset()))); comment("if (fromIndex >= count) { return -1; }"); cmpl(eax, esi); jcc(greater_equal, Constant(failure)); movl(edx, Address(ecx, Constant(String::offset_offset()))); addl(eax, edx); // i = offset + fromIndex addl(edx, esi); // int max = offset + count; movl(esi, Address(ecx, Constant(String::value_offset()))); // v = value. jmp(Constant(test)); bind(loop); cmpw(Address(esi, eax, times_2, Constant(Array::base_offset())), ebx); jcc(equal, Constant(success)); incl(eax); bind(test); cmpl(eax, edx); jcc(less, Constant(loop)); comment("Return -1 by pushing the value and jumping to the return address"); bind(failure); push_int(-1); jmp(edi); comment("Return i - offset by pushing the value and jumping to the return address"); bind(success); movl(esi, Address(ecx, Constant(String::offset_offset()))); // i = offset + fromIndex subl(eax, esi); push_int(eax); jmp(edi); rom_linkable_entry_end(); // native_string_indexof_entry } //----------------------java.lang.String.charAt--------------------------- { rom_linkable_entry("native_string_charAt_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String(java.lang.StringBuffer)------------- { rom_linkable_entry("native_string_init_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String.equals(java.lang.Object)------------ { rom_linkable_entry("native_string_equals_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String.indexOf(java.lang.String)----------- { rom_linkable_entry("native_string_indexof0_string_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String.indexOf(java.lang.String)----------- { rom_linkable_entry("native_string_indexof_string_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String.compareTo--------------------------- { // java.lang.String.compareTo // Method int compareTo(java.lang.String) rom_linkable_entry("native_string_compareTo_entry"); wtk_profile_quick_call(/* param_size*/ 2); comment("preserve method"); pushl(ebx); // 8 is return address plus pushed method int str1_offset = JavaFrame::arg_offset_from_sp(0) + 8, str0_offset = JavaFrame::arg_offset_from_sp(1) + 8; comment("load arguments to registers"); movl(ecx, Address(esp, Constant(str1_offset))); movl(eax, Address(esp, Constant(str0_offset))); // eax: str0: this String // ebx: str1: String to compare against Label bailout; comment("Null check"); testl(ecx, ecx); jcc(zero, Constant(bailout)); comment("get str0.value[]"); movl(esi, Address(eax, Constant(String::value_offset()))); comment("get str0.offset"); movl(ebx, Address(eax, Constant(String::offset_offset()))); comment("compute start of character data"); leal(esi, Address(esi, ebx, times_2, Constant(Array::base_offset()))); comment("get str0.count"); movl(eax, Address(eax, Constant(String::count_offset()))); comment("get str1.value[]"); movl(edi, Address(ecx, Constant(String::value_offset()))); comment("get str1.offset"); movl(ebx, Address(ecx, Constant(String::offset_offset()))); comment("compute start of character data"); leal(edi, Address(edi, ebx, times_2, Constant(Array::base_offset()))); comment("get str1.count"); movl(ebx, Address(ecx, Constant(String::count_offset()))); // esi = str0 start of character data // edi = str1 start of character data // eax = str0 length // ebx = str1 length Label str1_longest; subl(eax, ebx); jcc(greater_equal, Constant(str1_longest)); // str1 is longer than str0 addl(ebx, eax); bind(str1_longest); // esi = str0 start of character data // edi = str1 start of character data // eax = str0.count - str1.count // ebx = min(str0.count, str1.count) // save str0.count - str1.count, we might need it later pushl(eax); xorl(ecx, ecx); Label loop, check_lengths, done; bind(loop); cmpl(ecx, ebx); jcc(above_equal, Constant(check_lengths)); movzxw(eax, Address(esi, ecx, times_2)); movzxw(edx, Address(edi, ecx, times_2)); subl(eax, edx); jcc(not_equal, Constant(done)); incl(ecx); jmp(Constant(loop)); bind(check_lengths); movl(eax, Address(esp)); bind(done); popl(ebx); // remove saved length difference // Push result on stack and return to caller popl(ebx); // remove method popl(edi); // pop return address addl(esp, Constant(2 * BytesPerStackElement)); // remove arguments push_int(eax); // push result jmp(edi); // return comment("Bail out to the general compareTo implementation"); bind(bailout); comment("pop method"); popl(ebx); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); // native_string_compareTo_entry } //----------------------java.lang.String.endsWith---------------- { // java.lang.String.endsWith // Method boolean endsWith(java.lang.String) rom_linkable_entry("native_string_endsWith_entry"); wtk_profile_quick_call(/* param_size*/ 2); Label bailout; // 4 is return address int suffix_offset = JavaFrame::arg_offset_from_sp(0) + 4, this_offset = JavaFrame::arg_offset_from_sp(1) + 4; comment("load arguments to registers"); movl(eax, Address(esp, Constant(suffix_offset))); cmpl(eax, Constant(0)); jcc(equal, Constant(bailout)); movl(ecx, Address(esp, Constant(this_offset))); comment("Pop the return address"); popl(edi); movl(edx, Address(ecx, Constant(String::count_offset()))); subl(edx, Address(eax, Constant(String::count_offset()))); comment("Push (this.count - suffix.count) for toffset"); pushl(edx); comment("Push back the return address"); pushl(edi); jmp(Constant("native_string_startsWith_entry")); comment("Bail out to the general startsWith implementation"); bind(bailout); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); // native_string_endsWith_entry } //----------------------java.lang.String.startsWith---------------- { // java.lang.String.startsWith // Method boolean startsWith(java.lang.String) rom_linkable_entry("native_string_startsWith0_entry"); wtk_profile_quick_call(/* param_size*/ 2); Label bailout; // 4 is return address int prefix_offset = JavaFrame::arg_offset_from_sp(0) + 4; comment("Check if prefix is null"); cmpl(Address(esp, Constant(prefix_offset)), Constant(0)); jcc(equal, Constant(bailout)); comment("Pop the return address"); popl(edi); comment("Push zero for toffset"); pushl(Constant(0)); comment("Push back the return address"); pushl(edi); jmp(Constant("native_string_startsWith_entry")); comment("Bail out to the general startsWith implementation"); bind(bailout); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); // native_string_startsWith0_entry } { // ----------- java.lang.String.startsWith ------------------------------ // Method boolean startsWith(java.lang.String,int) rom_linkable_entry("native_string_startsWith_entry"); wtk_profile_quick_call(/* param_size*/ 3); Label bailout, return_false; // 4 is return address int prefix_offset = JavaFrame::arg_offset_from_sp(1) + 4; comment("Check if prefix is null"); cmpl(Address(esp, Constant(prefix_offset)), Constant(0)); jcc(equal, Constant(bailout)); comment("Pop the return address"); popl(edi); comment("Pop the argument: toffset"); pop_int(edx, edx); comment("Pop the argument: prefix"); pop_obj(eax, eax); comment("Pop the receiver"); pop_obj(ecx, ecx); comment("Preserve the return address"); pushl(edi); // ecx: this String // eax: prefix cmpl(edx, Constant(0)); jcc(less, Constant(return_false)); comment("if (toffset > this.count - prefix.count) return false;"); movl(ebx, Address(ecx, Constant(String::count_offset()))); subl(ebx, Address(eax, Constant(String::count_offset()))); cmpl(edx, ebx); jcc(greater, Constant(return_false)); comment("get this.value[]"); movl(esi, Address(ecx, Constant(String::value_offset()))); comment("get this.offset"); movl(ebx, Address(ecx, Constant(String::offset_offset()))); comment("add toffset"); addl(ebx, edx); comment("compute start of character data"); leal(esi, Address(esi, ebx, times_2, Constant(Array::base_offset()))); comment("get prefix.value[]"); movl(edi, Address(eax, Constant(String::value_offset()))); comment("get prefix.offset"); movl(ebx, Address(eax, Constant(String::offset_offset()))); comment("compute start of character data"); leal(edi, Address(edi, ebx, times_2, Constant(Array::base_offset()))); comment("get prefix.count"); movl(ecx, Address(eax, Constant(String::count_offset()))); comment("get the number of bytes to compare"); shll(ecx, Constant(1)); comment("memcmp(edi, esi, ecx);"); pushl(ecx); pushl(esi); pushl(edi); if (GenerateInlineAsm) { // VC++ treats memcmp() as an intrinsic function and would cause // reference to memcmp in Interpreter_i386.c to fail to compile. call(Constant("memcmp_from_interpreter")); } else { call(Constant("memcmp")); } addl(esp, Constant(12)); cmpl(eax, Constant(0)); jcc(not_equal, Constant(return_false)); // Push 1 on stack and return to caller popl(edi); // pop return address push_int(1); // push result jmp(edi); // return bind(return_false); // Push 0 on stack and return to caller popl(edi); // pop return address push_int(0); // push result jmp(edi); // return comment("Bail out to the general startsWith implementation"); bind(bailout); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); // native_string_startsWith_entry } }
// used by compiler only; may use only caller saved registers eax, ebx, ecx. // edx holds first int arg, esi, edi, ebp are callee-save & must be preserved. // Leave reciever in ecx; required behavior when +OptoArgsInRegisters // is modifed to put first oop in ecx. // // NOTE: If this code is used by the C1, the receiver_location is always 0. VtableStub* VtableStubs::create_vtable_stub(int vtable_index, int receiver_location) { const int i486_code_length = VtableStub::pd_code_size_limit(true); VtableStub* s = new(i486_code_length) VtableStub(true, vtable_index, receiver_location); ResourceMark rm; MacroAssembler* masm = new MacroAssembler(new CodeBuffer(s->entry_point(), i486_code_length)); #ifndef PRODUCT #ifdef COMPILER2 if (CountCompiledCalls) __ incl(Address((int)OptoRuntime::nof_megamorphic_calls_addr(), relocInfo::none)); #endif #endif // get receiver (need to skip return address on top of stack) #ifdef COMPILER1 assert(receiver_location == 0, "receiver is always in ecx - no location info needed"); #else if( receiver_location < SharedInfo::stack0 ) { assert(receiver_location == ECX_num, "receiver expected in ecx"); } else { __ movl(ecx, Address(esp, SharedInfo::reg2stack(OptoReg::Name(receiver_location)) * wordSize+wordSize/*skip return address*/)); } #endif // get receiver klass address npe_addr = __ pc(); __ movl(eax, Address(ecx, oopDesc::klass_offset_in_bytes())); // compute entry offset (in words) int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); #ifndef PRODUCT if (DebugVtables) { Label L; // check offset vs vtable length __ cmpl(Address(eax, instanceKlass::vtable_length_offset()*wordSize), vtable_index*vtableEntry::size()); __ jcc(Assembler::greater, L); __ movl(ebx, vtable_index); __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), ecx, ebx); __ bind(L); } #endif // PRODUCT // load methodOop and target address #ifdef COMPILER1 __ movl(ebx, Address(eax, entry_offset*wordSize + vtableEntry::method_offset_in_bytes())); address ame_addr = __ pc(); __ movl(edx, Address(ebx, methodOopDesc::from_compiled_code_entry_point_offset())); if (DebugVtables) { Label L; __ testl(edx, edx); __ jcc(Assembler::notZero, L); __ stop("Vtable entry is NULL"); __ bind(L); } // eax: receiver klass // ebx: methodOop // ecx: receiver // edx: entry point __ jmp(edx); #else __ movl(eax, Address(eax, entry_offset*wordSize + vtableEntry::method_offset_in_bytes())); address ame_addr = __ pc(); __ movl(ebx, Address(eax, methodOopDesc::from_compiled_code_entry_point_offset())); if (DebugVtables) { Label L; __ testl(ebx, ebx); __ jcc(Assembler::notZero, L); __ stop("Vtable entry is NULL"); __ bind(L); } // jump to target (either compiled code or c2iadapter) // eax: methodOop (in case we call c2iadapter) __ jmp(ebx); #endif // COMPILER1 masm->flush(); s->set_exception_points(npe_addr, ame_addr); return s; }