| 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_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 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 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 // Push space for the return value. | 284 // Push space for the return value. |
| 285 // Push the receiver. | 285 // Push the receiver. |
| 286 // Push IC data object. | 286 // Push IC data object. |
| 287 // Push arguments descriptor array. | 287 // Push arguments descriptor array. |
| 288 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); | 288 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); |
| 289 __ PushList((1 << R4) | (1 << R5) | (1 << R6) | (1 << IP)); | 289 __ PushList((1 << R4) | (1 << R5) | (1 << R6) | (1 << IP)); |
| 290 | 290 |
| 291 // R2: Smi-tagged arguments array length. | 291 // R2: Smi-tagged arguments array length. |
| 292 PushArgumentsArray(assembler); | 292 PushArgumentsArray(assembler); |
| 293 | 293 |
| 294 // Stack: | |
| 295 // TOS + 0: argument array. | |
| 296 // TOS + 1: arguments descriptor array. | |
| 297 // TOS + 2: IC data object. | |
| 298 // TOS + 3: Receiver. | |
| 299 // TOS + 4: place for result from the call. | |
| 300 // TOS + 5: saved FP of previous frame. | |
| 301 // TOS + 6: dart code return address | |
| 302 // TOS + 7: pc marker (0 for stub). | |
| 303 // TOS + 8: last argument of caller. | |
| 304 // .... | |
| 305 __ CallRuntime(kInstanceFunctionLookupRuntimeEntry); | 294 __ CallRuntime(kInstanceFunctionLookupRuntimeEntry); |
| 295 |
| 306 // Remove arguments. | 296 // Remove arguments. |
| 307 __ Drop(4); | 297 __ Drop(4); |
| 308 __ Pop(R0); // Get result into R0. | 298 __ Pop(R0); // Get result into R0. |
| 309 __ LeaveStubFrame(); | 299 __ LeaveStubFrame(); |
| 310 __ Ret(); | 300 __ Ret(); |
| 311 } | 301 } |
| 312 | 302 |
| 313 | 303 |
| 314 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 304 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
| 315 intptr_t deopt_reason, | 305 intptr_t deopt_reason, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 339 // +------------------+ | 329 // +------------------+ |
| 340 // | PC marker | | 330 // | PC marker | |
| 341 // +------------------+ | 331 // +------------------+ |
| 342 // | ... | <- SP of optimized frame | 332 // | ... | <- SP of optimized frame |
| 343 // | 333 // |
| 344 // Parts of the code cannot GC, part of the code can GC. | 334 // Parts of the code cannot GC, part of the code can GC. |
| 345 static void GenerateDeoptimizationSequence(Assembler* assembler, | 335 static void GenerateDeoptimizationSequence(Assembler* assembler, |
| 346 bool preserve_result) { | 336 bool preserve_result) { |
| 347 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there | 337 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
| 348 // is no need to set the correct PC marker or load PP, since they get patched. | 338 // is no need to set the correct PC marker or load PP, since they get patched. |
| 349 __ EnterFrame((1 << PP) | (1 << FP) | (1 << LR) | (1 << PC), 0); | 339 __ mov(IP, ShifterOperand(LR)); |
| 340 __ mov(LR, ShifterOperand(0)); |
| 341 __ EnterFrame((1 << PP) | (1 << FP) | (1 << IP) | (1 << LR), 0); |
| 350 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry | 342 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry |
| 351 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. | 343 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. |
| 352 const intptr_t saved_result_slot_from_fp = | 344 const intptr_t saved_result_slot_from_fp = |
| 353 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0); | 345 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0); |
| 354 // Result in R0 is preserved as part of pushing all registers below. | 346 // Result in R0 is preserved as part of pushing all registers below. |
| 355 | 347 |
| 356 // TODO(regis): Should we align the stack before pushing the fpu registers? | 348 // TODO(regis): Should we align the stack before pushing the fpu registers? |
| 357 // If we do, saved_r0_offset_from_fp is not constant anymore. | 349 // If we do, saved_r0_offset_from_fp is not constant anymore. |
| 358 | 350 |
| 359 // Push registers in their enumeration order: lowest register number at | 351 // Push registers in their enumeration order: lowest register number at |
| (...skipping 10 matching lines...) Expand all Loading... |
| 370 if (preserve_result) { | 362 if (preserve_result) { |
| 371 // Restore result into R1 temporarily. | 363 // Restore result into R1 temporarily. |
| 372 __ ldr(R1, Address(FP, saved_result_slot_from_fp * kWordSize)); | 364 __ ldr(R1, Address(FP, saved_result_slot_from_fp * kWordSize)); |
| 373 } | 365 } |
| 374 | 366 |
| 375 __ LeaveDartFrame(); | 367 __ LeaveDartFrame(); |
| 376 __ sub(SP, FP, ShifterOperand(R0)); | 368 __ sub(SP, FP, ShifterOperand(R0)); |
| 377 | 369 |
| 378 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there | 370 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
| 379 // is no need to set the correct PC marker or load PP, since they get patched. | 371 // is no need to set the correct PC marker or load PP, since they get patched. |
| 380 __ EnterFrame((1 << PP) | (1 << FP) | (1 << LR) | (1 << PC), 0); | 372 __ mov(IP, ShifterOperand(LR)); |
| 373 __ mov(LR, ShifterOperand(0)); |
| 374 __ EnterFrame((1 << PP) | (1 << FP) | (1 << IP) | (1 << LR), 0); |
| 381 __ mov(R0, ShifterOperand(FP)); // Get last FP address. | 375 __ mov(R0, ShifterOperand(FP)); // Get last FP address. |
| 382 if (preserve_result) { | 376 if (preserve_result) { |
| 383 __ Push(R1); // Preserve result as first local. | 377 __ Push(R1); // Preserve result as first local. |
| 384 } | 378 } |
| 385 __ ReserveAlignedFrameSpace(0); | 379 __ ReserveAlignedFrameSpace(0); |
| 386 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); // Pass last FP in R0. | 380 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); // Pass last FP in R0. |
| 387 if (preserve_result) { | 381 if (preserve_result) { |
| 388 // Restore result into R1. | 382 // Restore result into R1. |
| 389 __ ldr(R1, Address(FP, kFirstLocalSlotFromFp * kWordSize)); | 383 __ ldr(R1, Address(FP, kFirstLocalSlotFromFp * kWordSize)); |
| 390 } | 384 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 420 GenerateDeoptimizationSequence(assembler, true); // Preserve R0. | 414 GenerateDeoptimizationSequence(assembler, true); // Preserve R0. |
| 421 } | 415 } |
| 422 | 416 |
| 423 | 417 |
| 424 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 418 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
| 425 GenerateDeoptimizationSequence(assembler, false); // Don't preserve R0. | 419 GenerateDeoptimizationSequence(assembler, false); // Don't preserve R0. |
| 426 } | 420 } |
| 427 | 421 |
| 428 | 422 |
| 429 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { | 423 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { |
| 430 __ Unimplemented("MegamorphicMiss stub"); | 424 __ EnterStubFrame(); |
| 425 |
| 426 // Load the receiver. |
| 427 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
| 428 __ add(IP, FP, ShifterOperand(R2, LSL, 1)); // R2 is Smi. |
| 429 __ ldr(R6, Address(IP, kParamEndSlotFromFp * kWordSize)); |
| 430 |
| 431 // Preserve IC data and arguments descriptor. |
| 432 __ PushList((1 << R4) | (1 << R5)); |
| 433 |
| 434 // Push space for the return value. |
| 435 // Push the receiver. |
| 436 // Push IC data object. |
| 437 // Push arguments descriptor array. |
| 438 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); |
| 439 __ PushList((1 << R4) | (1 << R5) | (1 << R6) | (1 << IP)); |
| 440 |
| 441 // R2: Smi-tagged arguments array length. |
| 442 PushArgumentsArray(assembler); |
| 443 |
| 444 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry); |
| 445 // Remove arguments. |
| 446 __ Drop(4); |
| 447 __ Pop(R0); // Get result into R0. |
| 448 |
| 449 // Restore IC data and arguments descriptor. |
| 450 __ PopList((1 << R4) | (1 << R5)); |
| 451 |
| 452 __ LeaveStubFrame(); |
| 453 |
| 454 __ CompareImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 455 __ Branch(&StubCode::InstanceFunctionLookupLabel(), EQ); |
| 456 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag); |
| 457 __ bx(R0); |
| 431 } | 458 } |
| 432 | 459 |
| 433 | 460 |
| 434 // Called for inline allocation of arrays. | 461 // Called for inline allocation of arrays. |
| 435 // Input parameters: | 462 // Input parameters: |
| 436 // LR: return address. | 463 // LR: return address. |
| 437 // R2: array length as Smi. | 464 // R2: array length as Smi. |
| 438 // R1: array element type (either NULL or an instantiated type). | 465 // R1: array element type (either NULL or an instantiated type). |
| 439 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved. | 466 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved. |
| 440 // The newly allocated object is returned in R0. | 467 // The newly allocated object is returned in R0. |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 // calling into the runtime. | 665 // calling into the runtime. |
| 639 __ EnterStubFrame(); | 666 __ EnterStubFrame(); |
| 640 | 667 |
| 641 // Setup space on stack for result from error reporting. | 668 // Setup space on stack for result from error reporting. |
| 642 __ PushList((1 << R4) | (1 << R8)); // Arguments descriptor and raw null. | 669 __ PushList((1 << R4) | (1 << R8)); // Arguments descriptor and raw null. |
| 643 | 670 |
| 644 // Load smi-tagged arguments array length, including the non-closure. | 671 // Load smi-tagged arguments array length, including the non-closure. |
| 645 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 672 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
| 646 PushArgumentsArray(assembler); | 673 PushArgumentsArray(assembler); |
| 647 | 674 |
| 648 // Stack: | |
| 649 // TOS + 0: argument array. | |
| 650 // TOS + 1: arguments descriptor array. | |
| 651 // TOS + 2: place for result from the call. | |
| 652 // TOS + 3: saved FP of previous frame. | |
| 653 // TOS + 4: dart code return address | |
| 654 // TOS + 5: pc marker (0 for stub). | |
| 655 // TOS + 6: last argument of caller. | |
| 656 // .... | |
| 657 __ CallRuntime(kInvokeNonClosureRuntimeEntry); | 675 __ CallRuntime(kInvokeNonClosureRuntimeEntry); |
| 658 // Remove arguments. | 676 // Remove arguments. |
| 659 __ Drop(2); | 677 __ Drop(2); |
| 660 __ Pop(R0); // Get result into R0. | 678 __ Pop(R0); // Get result into R0. |
| 661 | 679 |
| 662 // Remove the stub frame as we are about to return. | 680 // Remove the stub frame as we are about to return. |
| 663 __ LeaveStubFrame(); | 681 __ LeaveStubFrame(); |
| 664 __ Ret(); | 682 __ Ret(); |
| 665 } | 683 } |
| 666 | 684 |
| (...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1260 } | 1278 } |
| 1261 __ Drop(1); // Pop function object. | 1279 __ Drop(1); // Pop function object. |
| 1262 __ Pop(R0); | 1280 __ Pop(R0); |
| 1263 // R0: new object | 1281 // R0: new object |
| 1264 // Restore the frame pointer. | 1282 // Restore the frame pointer. |
| 1265 __ LeaveStubFrame(true); | 1283 __ LeaveStubFrame(true); |
| 1266 __ Ret(); | 1284 __ Ret(); |
| 1267 } | 1285 } |
| 1268 | 1286 |
| 1269 | 1287 |
| 1288 // The target function was not found, so invoke method |
| 1289 // "dynamic noSuchMethod(Invocation invocation)". |
| 1290 // R5: inline cache data object. |
| 1291 // R4: arguments descriptor array. |
| 1270 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1292 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| 1271 __ Unimplemented("CallNoSuchMethodFunction stub"); | 1293 __ EnterStubFrame(); |
| 1294 |
| 1295 // Load the receiver. |
| 1296 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
| 1297 __ add(IP, FP, ShifterOperand(R2, LSL, 1)); // R2 is Smi. |
| 1298 __ ldr(R6, Address(IP, kParamEndSlotFromFp * kWordSize)); |
| 1299 |
| 1300 // Push space for the return value. |
| 1301 // Push the receiver. |
| 1302 // Push IC data object. |
| 1303 // Push arguments descriptor array. |
| 1304 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); |
| 1305 __ PushList((1 << R4) | (1 << R5) | (1 << R6) | (1 << IP)); |
| 1306 |
| 1307 // R2: Smi-tagged arguments array length. |
| 1308 PushArgumentsArray(assembler); |
| 1309 |
| 1310 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry); |
| 1311 // Remove arguments. |
| 1312 __ Drop(4); |
| 1313 __ Pop(R0); // Get result into R0. |
| 1314 __ LeaveStubFrame(); |
| 1315 __ Ret(); |
| 1272 } | 1316 } |
| 1273 | 1317 |
| 1274 | 1318 |
| 1275 // R6: function object. | 1319 // R6: function object. |
| 1276 // R5: inline cache data object. | 1320 // R5: inline cache data object. |
| 1277 // R4: arguments descriptor array. | 1321 // R4: arguments descriptor array. |
| 1278 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { | 1322 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { |
| 1279 Register ic_reg = R5; | 1323 Register ic_reg = R5; |
| 1280 Register func_reg = R6; | 1324 Register func_reg = R6; |
| 1281 if (FLAG_trace_optimized_ic_calls) { | 1325 if (FLAG_trace_optimized_ic_calls) { |
| (...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1947 __ Bind(&reference_compare); | 1991 __ Bind(&reference_compare); |
| 1948 __ cmp(left, ShifterOperand(right)); | 1992 __ cmp(left, ShifterOperand(right)); |
| 1949 __ Bind(&done); | 1993 __ Bind(&done); |
| 1950 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); | 1994 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); |
| 1951 __ Ret(); | 1995 __ Ret(); |
| 1952 } | 1996 } |
| 1953 | 1997 |
| 1954 } // namespace dart | 1998 } // namespace dart |
| 1955 | 1999 |
| 1956 #endif // defined TARGET_ARCH_ARM | 2000 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |