1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 /* 17 * Common subroutines and data. 18 */ 19 20 /* 21 * Common code when a backwards branch is taken 22 * 23 * On entry: 24 * ebx (a.k.a. rINST_FULL) -> PC adjustment in 16-bit words 25 */ 26 common_backwardBranch: 27 GET_GLUE(%ecx) 28 call common_periodicChecks # Note: expects rPC to be preserved 29 ADVANCE_PC_INDEXED(rINST_FULL) 30 FETCH_INST() 31 GOTO_NEXT 32 33 34 35 /* 36 * Common code for method invocation with range. 37 * 38 * On entry: 39 * eax = Method* methodToCall 40 * rINST trashed, must reload 41 */ 42 43 common_invokeMethodRange: 44 .LinvokeNewRange: 45 46 /* 47 * prepare to copy args to "outs" area of current frame 48 */ 49 50 movzbl 1(rPC),rINST_FULL # rINST_FULL<- AA 51 movzwl 4(rPC), %ecx # %ecx<- CCCC 52 SPILL(rPC) 53 SAVEAREA_FROM_FP(%edx,rFP) # %edx<- &StackSaveArea 54 test rINST_FULL, rINST_FULL 55 movl rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA 56 jz .LinvokeArgsDone # no args; jump to args done 57 58 59 /* 60 * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea) 61 * (very few methods have > 10 args; could unroll for common cases) 62 */ 63 64 movl %ebx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- save %ebx 65 lea (rFP, %ecx, 4), %ecx # %ecx<- &vCCCC 66 shll $$2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 67 subl LOCAL0_OFFSET(%ebp), %edx # %edx<- update &outs 68 shrl $$2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 69 1: 70 movl (%ecx), %ebx # %ebx<- vCCCC 71 lea 4(%ecx), %ecx # %ecx<- &vCCCC++ 72 subl $$1, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- LOCAL0_OFFSET-- 73 movl %ebx, (%edx) # *outs<- vCCCC 74 lea 4(%edx), %edx # outs++ 75 jne 1b # loop if count (LOCAL0_OFFSET(%ebp)) not zero 76 movl LOCAL1_OFFSET(%ebp), %ebx # %ebx<- restore %ebx 77 jmp .LinvokeArgsDone # continue 78 79 /* 80 * %eax is "Method* methodToCall", the method we're trying to call 81 * prepare to copy args to "outs" area of current frame 82 */ 83 84 common_invokeMethodNoRange: 85 .LinvokeNewNoRange: 86 movzbl 1(rPC),rINST_FULL # rINST_FULL<- BA 87 SPILL(rPC) 88 movl rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA 89 shrl $$4, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- B 90 je .LinvokeArgsDone # no args; jump to args done 91 movzwl 4(rPC), %ecx # %ecx<- GFED 92 SAVEAREA_FROM_FP(%edx,rFP) # %edx<- &StackSaveArea 93 94 /* 95 * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs 96 */ 97 98 .LinvokeNonRange: 99 cmp $$2, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 2 100 movl %ecx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- GFED 101 jl 1f # handle 1 arg 102 je 2f # handle 2 args 103 cmp $$4, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 4 104 jl 3f # handle 3 args 105 je 4f # handle 4 args 106 5: 107 andl $$15, rINST_FULL # rINST<- A 108 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 109 movl (rFP, rINST_FULL, 4), %ecx # %ecx<- vA 110 movl %ecx, (%edx) # *outs<- vA 111 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 112 4: 113 shr $$12, %ecx # %ecx<- G 114 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 115 movl (rFP, %ecx, 4), %ecx # %ecx<- vG 116 movl %ecx, (%edx) # *outs<- vG 117 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 118 3: 119 and $$0x0f00, %ecx # %ecx<- 0F00 120 shr $$8, %ecx # %ecx<- F 121 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 122 movl (rFP, %ecx, 4), %ecx # %ecx<- vF 123 movl %ecx, (%edx) # *outs<- vF 124 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 125 2: 126 and $$0x00f0, %ecx # %ecx<- 00E0 127 shr $$4, %ecx # %ecx<- E 128 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 129 movl (rFP, %ecx, 4), %ecx # %ecx<- vE 130 movl %ecx, (%edx) # *outs<- vE 131 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 132 1: 133 and $$0x000f, %ecx # %ecx<- 000D 134 movl (rFP, %ecx, 4), %ecx # %ecx<- vD 135 movl %ecx, -4(%edx) # *--outs<- vD 136 0: 137 138 /* 139 * %eax is "Method* methodToCall", the method we're trying to call 140 * find space for the new stack frame, check for overflow 141 */ 142 143 .LinvokeArgsDone: 144 movzwl offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize 145 movzwl offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize 146 movl %eax, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- methodToCall 147 shl $$2, %edx # %edx<- update offset 148 SAVEAREA_FROM_FP(%eax,rFP) # %eax<- &StackSaveArea 149 subl %edx, %eax # %eax<- newFP; (old savearea - regsSize) 150 GET_GLUE(%edx) # %edx<- pMterpGlue 151 movl %eax, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- &outs 152 subl $$sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP) 153 movl offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd 154 movl %edx, LOCAL2_OFFSET(%ebp) # LOCAL2_OFFSET<- glue->interpStackEnd 155 shl $$2, %ecx # %ecx<- update offset for outsSize 156 movl %eax, %edx # %edx<- newSaveArea 157 sub %ecx, %eax # %eax<- bottom; (newSaveArea - outsSize) 158 cmp LOCAL2_OFFSET(%ebp), %eax # compare interpStackEnd and bottom 159 movl LOCAL0_OFFSET(%ebp), %eax # %eax<- restore methodToCall 160 jl .LstackOverflow # handle frame overflow 161 162 /* 163 * set up newSaveArea 164 */ 165 166 #ifdef EASY_GDB 167 SAVEAREA_FROM_FP(%ecx,rFP) # %ecx<- &StackSaveArea 168 movl %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs 169 #endif 170 movl rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP 171 movl rPC_SPILL(%ebp), %ecx 172 movl %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC 173 testl $$ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call 174 movl %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call 175 jne .LinvokeNative # handle native call 176 177 /* 178 * Update "glue" values for the new method 179 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp 180 */ 181 182 movl offMethod_clazz(%eax), %edx # %edx<- method->clazz 183 GET_GLUE(%ecx) # %ecx<- pMterpGlue 184 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 185 movl %eax, offGlue_method(%ecx) # glue->method<- methodToCall 186 movl %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex 187 movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns 188 movl offGlue_self(%ecx), %eax # %eax<- glue->self 189 movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP 190 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP 191 FETCH_INST() 192 GOTO_NEXT # jump to methodToCall->insns 193 194 /* 195 * Prep for the native call 196 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea 197 */ 198 199 .LinvokeNative: 200 GET_GLUE(%ecx) # %ecx<- pMterpGlue 201 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 202 movl offGlue_self(%ecx), %ecx # %ecx<- glue->self 203 movl offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->... 204 movl %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top 205 movl %edx, OUT_ARG4(%esp) # save newSaveArea 206 movl LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP 207 movl %edx, offThread_curFrame(%ecx) # glue->self->curFrame<- newFP 208 movl %ecx, OUT_ARG3(%esp) # save glue->self 209 movl %ecx, OUT_ARG2(%esp) # push parameter glue->self 210 GET_GLUE(%ecx) # %ecx<- pMterpGlue 211 movl OUT_ARG1(%esp), %eax # %eax<- methodToCall 212 lea offGlue_retval(%ecx), %ecx # %ecx<- &retval 213 movl %ecx, OUT_ARG0(%esp) # push parameter pMterpGlue 214 push %edx # push parameter newFP 215 216 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc 217 lea 4(%esp), %esp 218 movl OUT_ARG4(%esp), %ecx # %ecx<- newSaveArea 219 movl OUT_ARG3(%esp), %eax # %eax<- glue->self 220 movl offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top 221 cmp $$0, offThread_exception(%eax) # check for exception 222 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP 223 movl %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top 224 UNSPILL(rPC) 225 jne common_exceptionThrown # handle exception 226 FETCH_INST_WORD(3) 227 ADVANCE_PC(3) 228 GOTO_NEXT # jump to next instruction 229 230 .LstackOverflow: # eax=methodToCall 231 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 232 GET_GLUE(%eax) # %eax<- pMterpGlue 233 movl offGlue_self(%eax), %eax # %eax<- glue->self 234 movl %eax, OUT_ARG0(%esp) # push parameter self 235 call dvmHandleStackOverflow # call: (Thread* self, Method* meth) 236 UNSPILL(rPC) # return: void 237 jmp common_exceptionThrown # handle exception 238 239 240 /* 241 * Common invoke code (old-style). 242 * TUNING: Rewrite along lines of new armv5 code? 243 * 244 * On entry: 245 * eax = Method* methodToCall 246 * ecx = bool methodCallRange 247 * rINST trashed, must reload 248 */ 249 common_invokeOld: 250 movl %ecx,OUT_ARG1(%esp) # arg1<- methodCallRange 251 GET_GLUE(%ecx) 252 movzwl (rPC),rINST_FULL # recover rINST 253 movl %eax,OUT_ARG2(%esp) # arg2<- method 254 movzwl 4(rPC),%eax # eax<- GFED or CCCC 255 SAVE_PC_TO_GLUE(%ecx) 256 SAVE_FP_TO_GLUE(%ecx) 257 movzbl rINST_HI,rINST_FULL 258 movl rINST_FULL,OUT_ARG3(%esp)# arg3<- AA 259 movl %ecx,OUT_ARG0(%esp) # arg0<- GLUE 260 movl %eax,OUT_ARG4(%esp) # arg4<- GFED/CCCC 261 call dvmMterp_invokeMethod 262 jmp common_resumeAfterGlueCall 263 264 265 /* 266 * Do we need the thread to be suspended or have debugger/profiling activity? 267 * 268 * On entry: 269 * ebx -> PC adjustment in 16-bit words (must be preserved) 270 * ecx -> GLUE pointer 271 * 272 * Note: A call will normally kill %eax, rPC/%edx and %ecx. To 273 * streamline the normal case, this routine will preserve rPC and 274 * %ecx in addition to the normal caller save regs. The save/restore 275 * is a bit ugly, but will happen in the relatively uncommon path. 276 * TUNING: Might be worthwhile to inline this. 277 * TODO: Basic-block style Jit will need a hook here as well. Fold it into 278 * the suspendCount check so we can get both in 1 shot. 279 */ 280 common_periodicChecks: 281 movl offGlue_pSelfSuspendCount(%ecx),%eax # eax <- &suspendCount 282 cmpl $$0,(%eax) 283 jne 1f 284 285 #if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 286 #if defined(WITH_DEBUGGER) 287 movl offGlue_pDebuggerActive(%ecx),%eax # eax <- &DebuggerActive 288 #endif 289 #if defined(WITH_PROFILER) 290 movl offGlue_pActiveProfilers(%ecx),%ecx # ecx <- &ActiveProfilers 291 #endif 292 #if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 293 movzbl (%eax),%eax # eax <- debuggerActive (boolean) 294 orl (%ecx),%eax # eax <- debuggerActive || activeProfilers 295 #elif defined(WITH_DEBUGGER) 296 movzbl (%eax),%eax # eax <- debuggerActive (boolean) 297 #elif defined(WITH_PROFILER) 298 movl (%ecx),%eax # eax <= activeProfilers 299 #endif 300 GET_GLUE(%ecx) # restore rGLUE 301 testl %eax,%eax 302 jne 3f # one or both active - switch interp 303 #endif 304 305 ret 306 307 /* Check for suspend */ 308 1: 309 /* At this point, the return pointer to the caller of 310 * common_periodicChecks is on the top of stack. We need to preserve 311 * rPC(edx) and GLUE(ecx). We'll spill rPC, and reload GLUE. 312 * The outgoing profile is: 313 * bool dvmCheckSuspendPending(Thread* self) 314 * Because we reached here via a call, go ahead and build a new frame. 315 */ 316 EXPORT_PC() # need for precise GC 317 movl offGlue_self(%ecx),%eax # eax<- glue->self 318 SPILL(rPC) # save edx 319 push %ebp 320 movl %esp,%ebp 321 subl $$24,%esp 322 movl %eax,OUT_ARG0(%esp) 323 call dvmCheckSuspendPending 324 addl $$24,%esp 325 pop %ebp 326 UNSPILL(rPC) 327 GET_GLUE(%ecx) 328 ret 329 330 /* Switch interpreters */ 331 /* Note: %ebx contains the 16-bit word offset to be applied to rPC to 332 * "complete" the interpretation of backwards branches. In effect, we 333 * are completing the interpretation of the branch instruction here, 334 * and the new interpreter will resume interpretation at the branch 335 * target. However, a switch request recognized during the handling 336 * of a return from method instruction results in an immediate abort, 337 * and the new interpreter will resume by re-interpreting the return 338 * instruction. 339 */ 340 3: 341 leal (rPC,%ebx,2),rPC # adjust pc to show target 342 GET_GLUE(%ecx) # bail expect GLUE already loaded 343 movl $$1,rINST_FULL # set changeInterp to true 344 jmp common_gotoBail 345 346 347 /* 348 * Common code for handling a return instruction 349 */ 350 common_returnFromMethod: 351 GET_GLUE(%ecx) 352 /* Set entry mode in case we bail */ 353 movb $$kInterpEntryReturn,offGlue_entryPoint(%ecx) 354 xorl rINST_FULL,rINST_FULL # zero offset in case we switch interps 355 call common_periodicChecks # Note: expects %ecx to be preserved 356 357 SAVEAREA_FROM_FP(%eax,rFP) # eax<- saveArea (old) 358 movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame 359 movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST_FULL 360 cmpl $$0,rINST_FULL # break? 361 je common_gotoBail # break frame, bail out completely 362 363 movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC 364 movl offGlue_self(%ecx),%eax # eax<- self 365 movl rINST_FULL,offGlue_method(%ecx) # glue->method = newSave->meethod 366 movl rFP,offThread_curFrame(%eax) # self->curFrame = fp 367 movl offMethod_clazz(rINST_FULL),%eax # eax<- method->clazz 368 FETCH_INST_WORD(3) 369 movl offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex 370 ADVANCE_PC(3) 371 movl %eax,offGlue_methodClassDex(%ecx) 372 /* not bailing - restore entry mode to default */ 373 movb $$kInterpEntryInstr,offGlue_entryPoint(%ecx) 374 GOTO_NEXT 375 376 /* 377 * Prepare to strip the current frame and "longjump" back to caller of 378 * dvmMterpStdRun. 379 * 380 * on entry: 381 * rINST_FULL holds changeInterp 382 * ecx holds glue pointer 383 * 384 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp) 385 */ 386 common_gotoBail: 387 SAVE_PC_TO_GLUE(%ecx) # export state to glue 388 SAVE_FP_TO_GLUE(%ecx) 389 movl %ecx,OUT_ARG0(%esp) # glue in arg0 390 movl rINST_FULL,OUT_ARG1(%esp) # changeInterp in arg1 391 call dvmMterpStdBail # bail out.... 392 393 394 /* 395 * After returning from a "glued" function, pull out the updated values 396 * and start executing at the next instruction. 397 */ 398 common_resumeAfterGlueCall: 399 GET_GLUE(%ecx) 400 LOAD_PC_FROM_GLUE(%ecx) 401 LOAD_FP_FROM_GLUE(%ecx) 402 FETCH_INST() 403 GOTO_NEXT 404 405 /* 406 * Integer divide or mod by zero 407 */ 408 common_errDivideByZero: 409 EXPORT_PC() 410 movl $$.LstrArithmeticException,%eax 411 movl %eax,OUT_ARG0(%esp) 412 movl $$.LstrDivideByZero,%eax 413 movl %eax,OUT_ARG1(%esp) 414 SPILL(rPC) 415 call dvmThrowException 416 UNSPILL(rPC) 417 jmp common_exceptionThrown 418 419 /* 420 * Attempt to allocate an array with a negative size. 421 */ 422 common_errNegativeArraySize: 423 EXPORT_PC() 424 movl $$.LstrNegativeArraySizeException,%eax 425 movl %eax,OUT_ARG0(%esp) 426 xorl %eax,%eax 427 movl %eax,OUT_ARG1(%esp) 428 SPILL(rPC) 429 call dvmThrowException 430 UNSPILL(rPC) 431 jmp common_exceptionThrown 432 433 /* 434 * Attempt to allocate an array with a negative size. 435 */ 436 common_errNoSuchMethod: 437 438 EXPORT_PC() 439 movl $$.LstrNoSuchMethodError,%eax 440 movl %eax,OUT_ARG0(%esp) 441 xorl %eax,%eax 442 movl %eax,OUT_ARG1(%esp) 443 SPILL(rPC) 444 call dvmThrowException 445 UNSPILL(rPC) 446 jmp common_exceptionThrown 447 448 /* 449 * Hit a null object when we weren't expecting one. Export the PC, throw a 450 * NullPointerException and goto the exception processing code. 451 */ 452 common_errNullObject: 453 EXPORT_PC() 454 movl $$.LstrNullPointerException,%eax 455 movl %eax,OUT_ARG0(%esp) 456 xorl %eax,%eax 457 movl %eax,OUT_ARG1(%esp) 458 SPILL(rPC) 459 call dvmThrowException 460 UNSPILL(rPC) 461 jmp common_exceptionThrown 462 463 /* 464 * Array index exceeds max. 465 */ 466 common_errArrayIndex: 467 EXPORT_PC() 468 movl $$.LstrArrayIndexException,%eax 469 movl %eax,OUT_ARG0(%esp) 470 xorl %eax,%eax 471 movl %eax,OUT_ARG1(%esp) 472 SPILL(rPC) 473 call dvmThrowException 474 UNSPILL(rPC) 475 jmp common_exceptionThrown 476 /* 477 * Invalid array value. 478 */ 479 common_errArrayStore: 480 EXPORT_PC() 481 movl $$.LstrArrayStoreException,%eax 482 movl %eax,OUT_ARG0(%esp) 483 xorl %eax,%eax 484 movl %eax,OUT_ARG1(%esp) 485 SPILL(rPC) 486 call dvmThrowException 487 UNSPILL(rPC) 488 jmp common_exceptionThrown 489 490 /* 491 * Somebody has thrown an exception. Handle it. 492 * 493 * If the exception processing code returns to us (instead of falling 494 * out of the interpreter), continue with whatever the next instruction 495 * now happens to be. 496 * 497 * This does not return. 498 */ 499 common_exceptionThrown: 500 GET_GLUE(%ecx) 501 SAVE_PC_TO_GLUE(%ecx) 502 SAVE_FP_TO_GLUE(%ecx) 503 movl %ecx,OUT_ARG0(%esp) 504 call dvmMterp_exceptionThrown 505 jmp common_resumeAfterGlueCall 506 507 common_abort: 508 movl $$0xdeadf00d,%eax 509 call *%eax 510 511 512 /* 513 * Strings 514 */ 515 516 .section .rodata 517 .LstrNullPointerException: 518 .asciz "Ljava/lang/NullPointerException;" 519 .LstrArithmeticException: 520 .asciz "Ljava/lang/ArithmeticException;" 521 .LstrDivideByZero: 522 .asciz "divide by zero" 523 .LstrArrayIndexException: 524 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 525 .LstrArrayStoreException: 526 .asciz "Ljava/lang/ArrayStoreException;" 527 .LstrNegativeArraySizeException: 528 .asciz "Ljava/lang/NegativeArraySizeException;" 529 .LstrInstantiationError: 530 .asciz "Ljava/lang/InstantiationError;" 531 .LstrClassCastException: 532 .asciz "Ljava/lang/ClassCastException;" 533 .LstrNoSuchMethodError: 534 .asciz "Ljava/lang/NoSuchMethodError;" 535 .LstrInternalError: 536 .asciz "Ljava/lang/InternalError;" 537 .LstrFilledNewArrayNotImpl: 538 .asciz "filled-new-array only implemented for 'int'" 539 540