| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 __ mov(CTX, A2); | 104 __ mov(CTX, A2); |
| 105 | 105 |
| 106 __ mov(SP, FP); | 106 __ mov(SP, FP); |
| 107 __ lw(RA, Address(SP, 1 * kWordSize)); | 107 __ lw(RA, Address(SP, 1 * kWordSize)); |
| 108 __ lw(FP, Address(SP, 0 * kWordSize)); | 108 __ lw(FP, Address(SP, 0 * kWordSize)); |
| 109 __ Ret(); | 109 __ Ret(); |
| 110 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); | 110 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); |
| 111 } | 111 } |
| 112 | 112 |
| 113 | 113 |
| 114 // Print the stop message. |
| 115 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, const char* message) { |
| 116 OS::Print("Stop message: %s\n", message); |
| 117 } |
| 118 END_LEAF_RUNTIME_ENTRY |
| 119 |
| 120 |
| 121 // Input parameters: |
| 122 // A0 : stop message (const char*). |
| 123 // Must preserve all registers. |
| 114 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) { | 124 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) { |
| 115 __ Unimplemented("PrintStopMessage stub"); | 125 __ EnterCallRuntimeFrame(0); |
| 126 // Call the runtime leaf function. A0 already contains the parameter. |
| 127 __ CallRuntime(kPrintStopMessageRuntimeEntry); |
| 128 __ LeaveCallRuntimeFrame(); |
| 129 __ Ret(); |
| 116 } | 130 } |
| 117 | 131 |
| 118 | 132 |
| 119 // Input parameters: | 133 // Input parameters: |
| 120 // RA : return address. | 134 // RA : return address. |
| 121 // SP : address of return value. | 135 // SP : address of return value. |
| 122 // T5 : address of the native function to call. | 136 // T5 : address of the native function to call. |
| 123 // A2 : address of first argument in argument array. | 137 // A2 : address of first argument in argument array. |
| 124 // A1 : argc_tag including number of arguments and function kind. | 138 // A1 : argc_tag including number of arguments and function kind. |
| 125 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { | 139 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 __ LeaveStubFrameAndReturn(T0); | 246 __ LeaveStubFrameAndReturn(T0); |
| 233 } | 247 } |
| 234 | 248 |
| 235 | 249 |
| 236 // Called from a static call only when an invalid code has been entered | 250 // Called from a static call only when an invalid code has been entered |
| 237 // (invalid because its function was optimized or deoptimized). | 251 // (invalid because its function was optimized or deoptimized). |
| 238 // S4: arguments descriptor array. | 252 // S4: arguments descriptor array. |
| 239 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 253 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
| 240 // Create a stub frame as we are pushing some objects on the stack before | 254 // Create a stub frame as we are pushing some objects on the stack before |
| 241 // calling into the runtime. | 255 // calling into the runtime. |
| 256 __ TraceSimMsg("FixCallersTarget"); |
| 242 __ EnterStubFrame(); | 257 __ EnterStubFrame(); |
| 243 // Setup space on stack for return value and preserve arguments descriptor. | 258 // Setup space on stack for return value and preserve arguments descriptor. |
| 244 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 259 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 245 __ sw(S4, Address(SP, 1 * kWordSize)); | 260 __ sw(S4, Address(SP, 1 * kWordSize)); |
| 246 __ sw(NULLREG, Address(SP, 0 * kWordSize)); | 261 __ sw(NULLREG, Address(SP, 0 * kWordSize)); |
| 247 __ CallRuntime(kFixCallersTargetRuntimeEntry); | 262 __ CallRuntime(kFixCallersTargetRuntimeEntry); |
| 248 // Get Code object result and restore arguments descriptor array. | 263 // Get Code object result and restore arguments descriptor array. |
| 249 __ lw(T0, Address(SP, 0 * kWordSize)); | 264 __ lw(T0, Address(SP, 0 * kWordSize)); |
| 250 __ lw(S4, Address(SP, 1 * kWordSize)); | 265 __ lw(S4, Address(SP, 1 * kWordSize)); |
| 251 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 266 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 __ addiu(SP, SP, Immediate(-4 * kWordSize)); | 332 __ addiu(SP, SP, Immediate(-4 * kWordSize)); |
| 318 __ sw(NULLREG, Address(SP, 3 * kWordSize)); | 333 __ sw(NULLREG, Address(SP, 3 * kWordSize)); |
| 319 __ sw(T1, Address(SP, 2 * kWordSize)); | 334 __ sw(T1, Address(SP, 2 * kWordSize)); |
| 320 __ sw(S5, Address(SP, 1 * kWordSize)); | 335 __ sw(S5, Address(SP, 1 * kWordSize)); |
| 321 __ sw(S4, Address(SP, 0 * kWordSize)); | 336 __ sw(S4, Address(SP, 0 * kWordSize)); |
| 322 | 337 |
| 323 // A1: Smi-tagged arguments array length. | 338 // A1: Smi-tagged arguments array length. |
| 324 PushArgumentsArray(assembler); | 339 PushArgumentsArray(assembler); |
| 325 __ TraceSimMsg("InstanceFunctionLookupStub return"); | 340 __ TraceSimMsg("InstanceFunctionLookupStub return"); |
| 326 | 341 |
| 327 // Stack: | |
| 328 // TOS + 0: argument array. | |
| 329 // TOS + 1: arguments descriptor array. | |
| 330 // TOS + 2: IC data object. | |
| 331 // TOS + 3: Receiver. | |
| 332 // TOS + 4: place for result from the call. | |
| 333 // TOS + 5: saved FP of previous frame. | |
| 334 // TOS + 6: dart code return address | |
| 335 // TOS + 7: pc marker (0 for stub). | |
| 336 // TOS + 8: last argument of caller. | |
| 337 // .... | |
| 338 __ CallRuntime(kInstanceFunctionLookupRuntimeEntry); | 342 __ CallRuntime(kInstanceFunctionLookupRuntimeEntry); |
| 339 | 343 |
| 340 __ lw(V0, Address(SP, 4 * kWordSize)); // Get result into V0. | 344 __ lw(V0, Address(SP, 4 * kWordSize)); // Get result into V0. |
| 341 __ addiu(SP, SP, Immediate(5 * kWordSize)); // Remove arguments. | 345 __ addiu(SP, SP, Immediate(5 * kWordSize)); // Remove arguments. |
| 342 | 346 |
| 343 __ LeaveStubFrameAndReturn(); | 347 __ LeaveStubFrameAndReturn(); |
| 344 } | 348 } |
| 345 | 349 |
| 346 | 350 |
| 347 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 351 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
| 348 intptr_t deopt_reason, | 352 intptr_t deopt_reason, |
| 349 uword saved_registers_address); | 353 uword saved_registers_address); |
| 350 | 354 |
| 351 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); | 355 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); |
| 352 | 356 |
| 353 | 357 |
| 358 |
| 359 |
| 354 // Used by eager and lazy deoptimization. Preserve result in V0 if necessary. | 360 // Used by eager and lazy deoptimization. Preserve result in V0 if necessary. |
| 355 // This stub translates optimized frame into unoptimized frame. The optimized | 361 // This stub translates optimized frame into unoptimized frame. The optimized |
| 356 // frame can contain values in registers and on stack, the unoptimized | 362 // frame can contain values in registers and on stack, the unoptimized |
| 357 // frame contains all values on stack. | 363 // frame contains all values on stack. |
| 358 // Deoptimization occurs in following steps: | 364 // Deoptimization occurs in following steps: |
| 359 // - Push all registers that can contain values. | 365 // - Push all registers that can contain values. |
| 360 // - Call C routine to copy the stack and saved registers into temporary buffer. | 366 // - Call C routine to copy the stack and saved registers into temporary buffer. |
| 361 // - Adjust caller's frame to correct unoptimized frame size. | 367 // - Adjust caller's frame to correct unoptimized frame size. |
| 362 // - Fill the unoptimized frame. | 368 // - Fill the unoptimized frame. |
| 363 // - Materialize objects that require allocation (e.g. Double instances). | 369 // - Materialize objects that require allocation (e.g. Double instances). |
| 364 // GC can occur only after frame is fully rewritten. | 370 // GC can occur only after frame is fully rewritten. |
| 365 // Stack after EnterFrame(...) below: | 371 // Stack after EnterFrame(...) below: |
| 366 // +------------------+ | 372 // +------------------+ |
| 367 // | Saved FP | <- TOS | 373 // | Saved PP | <- TOS |
| 368 // +------------------+ | 374 // +------------------+ |
| 369 // | return-address | (deoptimization point) | 375 // | Saved FP | <- FP of stub |
| 370 // +------------------+ | 376 // +------------------+ |
| 371 // | optimized frame | | 377 // | Saved LR | (deoptimization point) |
| 372 // | ... | | 378 // +------------------+ |
| 379 // | PC marker | |
| 380 // +------------------+ |
| 381 // | ... | <- SP of optimized frame |
| 373 // | 382 // |
| 374 // Parts of the code cannot GC, part of the code can GC. | 383 // Parts of the code cannot GC, part of the code can GC. |
| 375 static void GenerateDeoptimizationSequence(Assembler* assembler, | 384 static void GenerateDeoptimizationSequence(Assembler* assembler, |
| 376 bool preserve_result) { | 385 bool preserve_result) { |
| 386 __ TraceSimMsg("GenerateDeoptimizationSequence"); |
| 377 const intptr_t kPushedRegistersSize = | 387 const intptr_t kPushedRegistersSize = |
| 378 kNumberOfCpuRegisters * kWordSize + | 388 kNumberOfCpuRegisters * kWordSize + |
| 379 2 * kWordSize + // FP and RA. | 389 4 * kWordSize + // PP, FP, RA, PC marker. |
| 380 kNumberOfFRegisters * kWordSize; | 390 kNumberOfFRegisters * kWordSize; |
| 381 | 391 |
| 392 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
| 393 // is no need to set the correct PC marker or load PP, since they get patched. |
| 382 __ addiu(SP, SP, Immediate(-kPushedRegistersSize * kWordSize)); | 394 __ addiu(SP, SP, Immediate(-kPushedRegistersSize * kWordSize)); |
| 383 __ sw(RA, Address(SP, kPushedRegistersSize - 1 * kWordSize)); | 395 __ sw(ZR, Address(SP, kPushedRegistersSize - 1 * kWordSize)); |
| 384 __ sw(FP, Address(SP, kPushedRegistersSize - 2 * kWordSize)); | 396 __ sw(RA, Address(SP, kPushedRegistersSize - 2 * kWordSize)); |
| 385 __ addiu(FP, SP, Immediate(kPushedRegistersSize - 2 * kWordSize)); | 397 __ sw(FP, Address(SP, kPushedRegistersSize - 3 * kWordSize)); |
| 386 | 398 __ sw(PP, Address(SP, kPushedRegistersSize - 4 * kWordSize)); |
| 399 __ addiu(FP, SP, Immediate(kPushedRegistersSize - 3 * kWordSize)); |
| 387 | 400 |
| 388 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry | 401 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry |
| 389 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. | 402 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. |
| 390 const intptr_t saved_v0_offset_from_fp = -(kNumberOfCpuRegisters - V0); | 403 const intptr_t saved_result_slot_from_fp = |
| 404 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - V0); |
| 391 // Result in V0 is preserved as part of pushing all registers below. | 405 // Result in V0 is preserved as part of pushing all registers below. |
| 392 | 406 |
| 407 // TODO(regis): Should we align the stack before pushing the fpu registers? |
| 408 // If we do, saved_result_slot_from_fp is not constant anymore. |
| 409 |
| 393 // Push registers in their enumeration order: lowest register number at | 410 // Push registers in their enumeration order: lowest register number at |
| 394 // lowest address. | 411 // lowest address. |
| 395 for (int i = 0; i < kNumberOfCpuRegisters; i++) { | 412 for (int i = 0; i < kNumberOfCpuRegisters; i++) { |
| 396 const int slot = 2 + kNumberOfCpuRegisters - i; | 413 const int slot = 4 + kNumberOfCpuRegisters - i; |
| 397 Register reg = static_cast<Register>(i); | 414 Register reg = static_cast<Register>(i); |
| 398 __ sw(reg, Address(SP, kPushedRegistersSize - slot * kWordSize)); | 415 __ sw(reg, Address(SP, kPushedRegistersSize - slot * kWordSize)); |
| 399 } | 416 } |
| 400 for (int i = 0; i < kNumberOfFRegisters; i++) { | 417 for (int i = 0; i < kNumberOfFRegisters; i++) { |
| 401 // These go below the CPU registers. | 418 // These go below the CPU registers. |
| 402 const int slot = 2 + kNumberOfCpuRegisters + kNumberOfFRegisters - i; | 419 const int slot = 4 + kNumberOfCpuRegisters + kNumberOfFRegisters - i; |
| 403 FRegister reg = static_cast<FRegister>(i); | 420 FRegister reg = static_cast<FRegister>(i); |
| 404 __ swc1(reg, Address(SP, kPushedRegistersSize - slot * kWordSize)); | 421 __ swc1(reg, Address(SP, kPushedRegistersSize - slot * kWordSize)); |
| 405 } | 422 } |
| 406 | 423 |
| 407 __ mov(A0, SP); // Pass address of saved registers block. | 424 __ mov(A0, SP); // Pass address of saved registers block. |
| 408 __ ReserveAlignedFrameSpace(0); | 425 __ ReserveAlignedFrameSpace(0); |
| 409 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); | 426 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); |
| 410 // Result (V0) is stack-size (FP - SP) in bytes, incl. the return address. | 427 // Result (V0) is stack-size (FP - SP) in bytes, incl. the return address. |
| 411 | 428 |
| 412 if (preserve_result) { | 429 if (preserve_result) { |
| 413 // Restore result into T1 temporarily. | 430 // Restore result into T1 temporarily. |
| 414 __ lw(T1, Address(FP, saved_v0_offset_from_fp * kWordSize)); | 431 __ lw(T1, Address(FP, saved_result_slot_from_fp * kWordSize)); |
| 415 } | 432 } |
| 416 | 433 |
| 417 __ mov(SP, FP); | 434 __ addiu(SP, FP, Immediate(-kWordSize)); |
| 418 __ lw(FP, Address(SP, 0 * kWordSize)); | 435 __ lw(RA, Address(SP, 2 * kWordSize)); |
| 419 __ lw(RA, Address(SP, 1 * kWordSize)); | 436 __ lw(FP, Address(SP, 1 * kWordSize)); |
| 420 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 437 __ lw(PP, Address(SP, 0 * kWordSize)); |
| 421 | |
| 422 __ subu(SP, FP, V0); | 438 __ subu(SP, FP, V0); |
| 423 | 439 |
| 424 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 440 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
| 425 __ sw(RA, Address(SP, 1 * kWordSize)); | 441 // is no need to set the correct PC marker or load PP, since they get patched. |
| 426 __ sw(FP, Address(SP, 0 * kWordSize)); | 442 __ addiu(SP, SP, Immediate(-4 * kWordSize)); |
| 427 __ mov(FP, SP); | 443 __ sw(ZR, Address(SP, 3 * kWordSize)); |
| 444 __ sw(RA, Address(SP, 2 * kWordSize)); |
| 445 __ sw(FP, Address(SP, 1 * kWordSize)); |
| 446 __ sw(PP, Address(SP, 0 * kWordSize)); |
| 447 __ addiu(FP, SP, Immediate(kWordSize)); |
| 428 | 448 |
| 429 __ mov(A0, SP); // Get last FP address. | 449 __ mov(A0, FP); // Get last FP address. |
| 430 if (preserve_result) { | 450 if (preserve_result) { |
| 431 __ Push(T1); // Preserve result. | 451 __ Push(T1); // Preserve result as first local. |
| 432 } | 452 } |
| 433 __ ReserveAlignedFrameSpace(0); | 453 __ ReserveAlignedFrameSpace(0); |
| 434 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); // Pass last FP in A0. | 454 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); // Pass last FP in A0. |
| 435 // Result (V0) is our FP. | |
| 436 if (preserve_result) { | 455 if (preserve_result) { |
| 437 // Restore result into T1. | 456 // Restore result into T1. |
| 438 __ lw(T1, Address(FP, -1 * kWordSize)); | 457 __ lw(T1, Address(FP, kFirstLocalSlotFromFp * kWordSize)); |
| 439 } | 458 } |
| 440 // Code above cannot cause GC. | 459 // Code above cannot cause GC. |
| 441 __ mov(SP, FP); | 460 __ addiu(SP, FP, Immediate(-kWordSize)); |
| 442 __ lw(FP, Address(SP, 0 * kWordSize)); | 461 __ lw(RA, Address(SP, 2 * kWordSize)); |
| 443 __ lw(RA, Address(SP, 1 * kWordSize)); | 462 __ lw(FP, Address(SP, 1 * kWordSize)); |
| 444 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 463 __ lw(PP, Address(SP, 0 * kWordSize)); |
| 445 __ mov(FP, V0); | 464 __ addiu(SP, SP, Immediate(4 * kWordSize)); |
| 446 | 465 |
| 447 // Frame is fully rewritten at this point and it is safe to perform a GC. | 466 // Frame is fully rewritten at this point and it is safe to perform a GC. |
| 448 // Materialize any objects that were deferred by FillFrame because they | 467 // Materialize any objects that were deferred by FillFrame because they |
| 449 // require allocation. | 468 // require allocation. |
| 450 __ EnterStubFrame(); | 469 __ EnterStubFrame(); |
| 451 if (preserve_result) { | 470 if (preserve_result) { |
| 452 __ Push(T1); // Preserve result, it will be GC-d here. | 471 __ Push(T1); // Preserve result, it will be GC-d here. |
| 453 } | 472 } |
| 454 __ PushObject(Smi::ZoneHandle()); // Space for the result. | 473 __ PushObject(Smi::ZoneHandle()); // Space for the result. |
| 455 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry); | 474 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry); |
| 456 // Result tells stub how many bytes to remove from the expression stack | 475 // Result tells stub how many bytes to remove from the expression stack |
| 457 // of the bottom-most frame. They were used as materialization arguments. | 476 // of the bottom-most frame. They were used as materialization arguments. |
| 458 __ Pop(T1); | 477 __ Pop(T1); |
| 459 __ SmiUntag(T1); | |
| 460 if (preserve_result) { | 478 if (preserve_result) { |
| 461 __ Pop(V0); // Restore result. | 479 __ Pop(V0); // Restore result. |
| 462 } | 480 } |
| 463 __ LeaveStubFrame(); | 481 __ LeaveStubFrame(); |
| 464 | 482 // Remove materialization arguments. |
| 465 // Return. | 483 __ SmiUntag(T1); |
| 466 __ jr(RA); | 484 __ addu(SP, SP, T1); |
| 467 __ delay_slot()->addu(SP, SP, T1); // Remove materialization arguments. | 485 __ Ret(); |
| 468 } | 486 } |
| 469 | 487 |
| 470 | 488 |
| 471 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { | 489 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { |
| 472 __ Unimplemented("DeoptimizeLazy stub"); | 490 // Correct return address to point just after the call that is being |
| 491 // deoptimized. |
| 492 __ AddImmediate(RA, -CallPattern::kFixedLengthInBytes); |
| 493 GenerateDeoptimizationSequence(assembler, true); // Preserve V0. |
| 473 } | 494 } |
| 474 | 495 |
| 475 | 496 |
| 476 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 497 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
| 477 GenerateDeoptimizationSequence(assembler, false); // Don't preserve V0. | 498 GenerateDeoptimizationSequence(assembler, false); // Don't preserve V0. |
| 478 } | 499 } |
| 479 | 500 |
| 480 | 501 |
| 481 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { | 502 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { |
| 482 __ Unimplemented("MegamorphicMiss stub"); | 503 __ Unimplemented("MegamorphicMiss stub"); |
| 504 return; |
| 483 } | 505 } |
| 484 | 506 |
| 485 | 507 |
| 486 // Called for inline allocation of arrays. | 508 // Called for inline allocation of arrays. |
| 487 // Input parameters: | 509 // Input parameters: |
| 488 // RA: return address. | 510 // RA: return address. |
| 489 // A1: Array length as Smi. | 511 // A1: Array length as Smi. |
| 490 // A0: array element type (either NULL or an instantiated type). | 512 // A0: array element type (either NULL or an instantiated type). |
| 491 // NOTE: A1 cannot be clobbered here as the caller relies on it being saved. | 513 // NOTE: A1 cannot be clobbered here as the caller relies on it being saved. |
| 492 // The newly allocated object is returned in V0. | 514 // The newly allocated object is returned in V0. |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 __ LeaveStubFrameAndReturn(); | 881 __ LeaveStubFrameAndReturn(); |
| 860 } | 882 } |
| 861 | 883 |
| 862 | 884 |
| 863 // Called for inline allocation of contexts. | 885 // Called for inline allocation of contexts. |
| 864 // Input: | 886 // Input: |
| 865 // T1: number of context variables. | 887 // T1: number of context variables. |
| 866 // Output: | 888 // Output: |
| 867 // V0: new allocated RawContext object. | 889 // V0: new allocated RawContext object. |
| 868 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 890 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
| 891 __ TraceSimMsg("AllocateContext"); |
| 869 if (FLAG_inline_alloc) { | 892 if (FLAG_inline_alloc) { |
| 870 const Class& context_class = Class::ZoneHandle(Object::context_class()); | 893 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
| 871 Label slow_case; | 894 Label slow_case; |
| 872 Heap* heap = Isolate::Current()->heap(); | 895 Heap* heap = Isolate::Current()->heap(); |
| 873 // First compute the rounded instance size. | 896 // First compute the rounded instance size. |
| 874 // T1: number of context variables. | 897 // T1: number of context variables. |
| 875 intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1; | 898 intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1; |
| 876 __ LoadImmediate(T2, fixed_size); | 899 __ LoadImmediate(T2, fixed_size); |
| 877 __ sll(T0, T1, 2); | 900 __ sll(T0, T1, 2); |
| 878 __ addu(T2, T2, T0); | 901 __ addu(T2, T2, T0); |
| (...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1750 __ LeaveDartFrameAndReturn(); | 1773 __ LeaveDartFrameAndReturn(); |
| 1751 } | 1774 } |
| 1752 | 1775 |
| 1753 | 1776 |
| 1754 // RA: return address (Dart code). | 1777 // RA: return address (Dart code). |
| 1755 // S5: Inline cache data array. | 1778 // S5: Inline cache data array. |
| 1756 // S4: Arguments descriptor array. | 1779 // S4: Arguments descriptor array. |
| 1757 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1780 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
| 1758 // Create a stub frame as we are pushing some objects on the stack before | 1781 // Create a stub frame as we are pushing some objects on the stack before |
| 1759 // calling into the runtime. | 1782 // calling into the runtime. |
| 1783 __ TraceSimMsg("BreakpointDynamicStub"); |
| 1760 __ EnterStubFrame(); | 1784 __ EnterStubFrame(); |
| 1761 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1785 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 1762 __ sw(S5, Address(SP, 1 * kWordSize)); | 1786 __ sw(S5, Address(SP, 1 * kWordSize)); |
| 1763 __ sw(S4, Address(SP, 0 * kWordSize)); | 1787 __ sw(S4, Address(SP, 0 * kWordSize)); |
| 1764 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); | 1788 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); |
| 1765 __ lw(S4, Address(SP, 0 * kWordSize)); | 1789 __ lw(S4, Address(SP, 0 * kWordSize)); |
| 1766 __ lw(S5, Address(SP, 1 * kWordSize)); | 1790 __ lw(S5, Address(SP, 1 * kWordSize)); |
| 1767 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 1791 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
| 1768 __ LeaveStubFrame(); | 1792 __ LeaveStubFrame(); |
| 1769 | 1793 |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2130 __ CallRuntime(kBigintCompareRuntimeEntry); | 2154 __ CallRuntime(kBigintCompareRuntimeEntry); |
| 2131 __ TraceSimMsg("IdenticalWithNumberCheckStub return"); | 2155 __ TraceSimMsg("IdenticalWithNumberCheckStub return"); |
| 2132 // Result in V0, 0 means equal. | 2156 // Result in V0, 0 means equal. |
| 2133 __ LeaveStubFrame(); | 2157 __ LeaveStubFrame(); |
| 2134 __ b(&done); | 2158 __ b(&done); |
| 2135 __ delay_slot()->mov(CMPRES, V0); | 2159 __ delay_slot()->mov(CMPRES, V0); |
| 2136 | 2160 |
| 2137 __ Bind(&reference_compare); | 2161 __ Bind(&reference_compare); |
| 2138 __ subu(ret, left, right); | 2162 __ subu(ret, left, right); |
| 2139 __ Bind(&done); | 2163 __ Bind(&done); |
| 2164 // A branch or test after this comparison will check CMPRES == TMP1. |
| 2165 __ mov(TMP1, ZR); |
| 2140 __ lw(T0, Address(SP, 0 * kWordSize)); | 2166 __ lw(T0, Address(SP, 0 * kWordSize)); |
| 2141 __ lw(T1, Address(SP, 1 * kWordSize)); | 2167 __ lw(T1, Address(SP, 1 * kWordSize)); |
| 2142 __ Ret(); | 2168 __ Ret(); |
| 2143 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); | 2169 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); |
| 2144 } | 2170 } |
| 2145 | 2171 |
| 2146 } // namespace dart | 2172 } // namespace dart |
| 2147 | 2173 |
| 2148 #endif // defined TARGET_ARCH_MIPS | 2174 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |