| 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/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset()); | 96 __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset()); |
| 97 | 97 |
| 98 // Reset exit frame information in Isolate structure. | 98 // Reset exit frame information in Isolate structure. |
| 99 __ LoadImmediate(R2, 0); | 99 __ LoadImmediate(R2, 0); |
| 100 __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset()); | 100 __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset()); |
| 101 | 101 |
| 102 __ LeaveStubFrame(); | 102 __ LeaveStubFrame(); |
| 103 __ Ret(); | 103 __ Ret(); |
| 104 } | 104 } |
| 105 | 105 |
| 106 | |
| 107 // Print the stop message. | 106 // Print the stop message. |
| 108 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) { | 107 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) { |
| 109 OS::Print("Stop message: %s\n", message); | 108 OS::Print("Stop message: %s\n", message); |
| 110 } | 109 } |
| 111 END_LEAF_RUNTIME_ENTRY | 110 END_LEAF_RUNTIME_ENTRY |
| 112 | 111 |
| 113 | |
| 114 // Input parameters: | 112 // Input parameters: |
| 115 // R0 : stop message (const char*). | 113 // R0 : stop message (const char*). |
| 116 // Must preserve all registers. | 114 // Must preserve all registers. |
| 117 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) { | 115 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) { |
| 118 __ EnterCallRuntimeFrame(0); | 116 __ EnterCallRuntimeFrame(0); |
| 119 // Call the runtime leaf function. R0 already contains the parameter. | 117 // Call the runtime leaf function. R0 already contains the parameter. |
| 120 __ CallRuntime(kPrintStopMessageRuntimeEntry, 1); | 118 __ CallRuntime(kPrintStopMessageRuntimeEntry, 1); |
| 121 __ LeaveCallRuntimeFrame(); | 119 __ LeaveCallRuntimeFrame(); |
| 122 __ Ret(); | 120 __ Ret(); |
| 123 } | 121 } |
| 124 | 122 |
| 125 | |
| 126 // Input parameters: | 123 // Input parameters: |
| 127 // LR : return address. | 124 // LR : return address. |
| 128 // SP : address of return value. | 125 // SP : address of return value. |
| 129 // R9 : address of the native function to call. | 126 // R9 : address of the native function to call. |
| 130 // R2 : address of first argument in argument array. | 127 // R2 : address of first argument in argument array. |
| 131 // R1 : argc_tag including number of arguments and function kind. | 128 // R1 : argc_tag including number of arguments and function kind. |
| 132 static void GenerateCallNativeWithWrapperStub(Assembler* assembler, | 129 static void GenerateCallNativeWithWrapperStub(Assembler* assembler, |
| 133 Address wrapper) { | 130 Address wrapper) { |
| 134 const intptr_t thread_offset = NativeArguments::thread_offset(); | 131 const intptr_t thread_offset = NativeArguments::thread_offset(); |
| 135 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); | 132 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset()); | 195 __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset()); |
| 199 | 196 |
| 200 // Reset exit frame information in Isolate structure. | 197 // Reset exit frame information in Isolate structure. |
| 201 __ LoadImmediate(R2, 0); | 198 __ LoadImmediate(R2, 0); |
| 202 __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset()); | 199 __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset()); |
| 203 | 200 |
| 204 __ LeaveStubFrame(); | 201 __ LeaveStubFrame(); |
| 205 __ Ret(); | 202 __ Ret(); |
| 206 } | 203 } |
| 207 | 204 |
| 208 | |
| 209 void StubCode::GenerateCallNoScopeNativeStub(Assembler* assembler) { | 205 void StubCode::GenerateCallNoScopeNativeStub(Assembler* assembler) { |
| 210 GenerateCallNativeWithWrapperStub( | 206 GenerateCallNativeWithWrapperStub( |
| 211 assembler, | 207 assembler, |
| 212 Address(THR, Thread::no_scope_native_wrapper_entry_point_offset())); | 208 Address(THR, Thread::no_scope_native_wrapper_entry_point_offset())); |
| 213 } | 209 } |
| 214 | 210 |
| 215 | |
| 216 void StubCode::GenerateCallAutoScopeNativeStub(Assembler* assembler) { | 211 void StubCode::GenerateCallAutoScopeNativeStub(Assembler* assembler) { |
| 217 GenerateCallNativeWithWrapperStub( | 212 GenerateCallNativeWithWrapperStub( |
| 218 assembler, | 213 assembler, |
| 219 Address(THR, Thread::auto_scope_native_wrapper_entry_point_offset())); | 214 Address(THR, Thread::auto_scope_native_wrapper_entry_point_offset())); |
| 220 } | 215 } |
| 221 | 216 |
| 222 | |
| 223 // Input parameters: | 217 // Input parameters: |
| 224 // LR : return address. | 218 // LR : return address. |
| 225 // SP : address of return value. | 219 // SP : address of return value. |
| 226 // R9 : address of the native function to call. | 220 // R9 : address of the native function to call. |
| 227 // R2 : address of first argument in argument array. | 221 // R2 : address of first argument in argument array. |
| 228 // R1 : argc_tag including number of arguments and function kind. | 222 // R1 : argc_tag including number of arguments and function kind. |
| 229 void StubCode::GenerateCallBootstrapNativeStub(Assembler* assembler) { | 223 void StubCode::GenerateCallBootstrapNativeStub(Assembler* assembler) { |
| 230 const intptr_t thread_offset = NativeArguments::thread_offset(); | 224 const intptr_t thread_offset = NativeArguments::thread_offset(); |
| 231 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); | 225 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); |
| 232 const intptr_t argv_offset = NativeArguments::argv_offset(); | 226 const intptr_t argv_offset = NativeArguments::argv_offset(); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset()); | 285 __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset()); |
| 292 | 286 |
| 293 // Reset exit frame information in Isolate structure. | 287 // Reset exit frame information in Isolate structure. |
| 294 __ LoadImmediate(R2, 0); | 288 __ LoadImmediate(R2, 0); |
| 295 __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset()); | 289 __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset()); |
| 296 | 290 |
| 297 __ LeaveStubFrame(); | 291 __ LeaveStubFrame(); |
| 298 __ Ret(); | 292 __ Ret(); |
| 299 } | 293 } |
| 300 | 294 |
| 301 | |
| 302 // Input parameters: | 295 // Input parameters: |
| 303 // R4: arguments descriptor array. | 296 // R4: arguments descriptor array. |
| 304 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { | 297 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
| 305 // Create a stub frame as we are pushing some objects on the stack before | 298 // Create a stub frame as we are pushing some objects on the stack before |
| 306 // calling into the runtime. | 299 // calling into the runtime. |
| 307 __ EnterStubFrame(); | 300 __ EnterStubFrame(); |
| 308 // Setup space on stack for return value and preserve arguments descriptor. | 301 // Setup space on stack for return value and preserve arguments descriptor. |
| 309 __ LoadImmediate(R0, 0); | 302 __ LoadImmediate(R0, 0); |
| 310 __ PushList((1 << R0) | (1 << R4)); | 303 __ PushList((1 << R0) | (1 << R4)); |
| 311 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); | 304 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); |
| 312 // Get Code object result and restore arguments descriptor array. | 305 // Get Code object result and restore arguments descriptor array. |
| 313 __ PopList((1 << R0) | (1 << R4)); | 306 __ PopList((1 << R0) | (1 << R4)); |
| 314 // Remove the stub frame. | 307 // Remove the stub frame. |
| 315 __ LeaveStubFrame(); | 308 __ LeaveStubFrame(); |
| 316 // Jump to the dart function. | 309 // Jump to the dart function. |
| 317 __ mov(CODE_REG, Operand(R0)); | 310 __ mov(CODE_REG, Operand(R0)); |
| 318 __ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); | 311 __ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); |
| 319 __ bx(R0); | 312 __ bx(R0); |
| 320 } | 313 } |
| 321 | 314 |
| 322 | |
| 323 // Called from a static call only when an invalid code has been entered | 315 // Called from a static call only when an invalid code has been entered |
| 324 // (invalid because its function was optimized or deoptimized). | 316 // (invalid because its function was optimized or deoptimized). |
| 325 // R4: arguments descriptor array. | 317 // R4: arguments descriptor array. |
| 326 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 318 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
| 327 // Load code pointer to this stub from the thread: | 319 // Load code pointer to this stub from the thread: |
| 328 // The one that is passed in, is not correct - it points to the code object | 320 // The one that is passed in, is not correct - it points to the code object |
| 329 // that needs to be replaced. | 321 // that needs to be replaced. |
| 330 __ ldr(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset())); | 322 __ ldr(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset())); |
| 331 // Create a stub frame as we are pushing some objects on the stack before | 323 // Create a stub frame as we are pushing some objects on the stack before |
| 332 // calling into the runtime. | 324 // calling into the runtime. |
| 333 __ EnterStubFrame(); | 325 __ EnterStubFrame(); |
| 334 // Setup space on stack for return value and preserve arguments descriptor. | 326 // Setup space on stack for return value and preserve arguments descriptor. |
| 335 __ LoadImmediate(R0, 0); | 327 __ LoadImmediate(R0, 0); |
| 336 __ PushList((1 << R0) | (1 << R4)); | 328 __ PushList((1 << R0) | (1 << R4)); |
| 337 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); | 329 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); |
| 338 // Get Code object result and restore arguments descriptor array. | 330 // Get Code object result and restore arguments descriptor array. |
| 339 __ PopList((1 << R0) | (1 << R4)); | 331 __ PopList((1 << R0) | (1 << R4)); |
| 340 // Remove the stub frame. | 332 // Remove the stub frame. |
| 341 __ LeaveStubFrame(); | 333 __ LeaveStubFrame(); |
| 342 // Jump to the dart function. | 334 // Jump to the dart function. |
| 343 __ mov(CODE_REG, Operand(R0)); | 335 __ mov(CODE_REG, Operand(R0)); |
| 344 __ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); | 336 __ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); |
| 345 __ bx(R0); | 337 __ bx(R0); |
| 346 } | 338 } |
| 347 | 339 |
| 348 | |
| 349 // Called from object allocate instruction when the allocation stub has been | 340 // Called from object allocate instruction when the allocation stub has been |
| 350 // disabled. | 341 // disabled. |
| 351 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { | 342 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { |
| 352 // Load code pointer to this stub from the thread: | 343 // Load code pointer to this stub from the thread: |
| 353 // The one that is passed in, is not correct - it points to the code object | 344 // The one that is passed in, is not correct - it points to the code object |
| 354 // that needs to be replaced. | 345 // that needs to be replaced. |
| 355 __ ldr(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset())); | 346 __ ldr(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset())); |
| 356 __ EnterStubFrame(); | 347 __ EnterStubFrame(); |
| 357 // Setup space on stack for return value. | 348 // Setup space on stack for return value. |
| 358 __ LoadImmediate(R0, 0); | 349 __ LoadImmediate(R0, 0); |
| 359 __ Push(R0); | 350 __ Push(R0); |
| 360 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); | 351 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); |
| 361 // Get Code object result. | 352 // Get Code object result. |
| 362 __ Pop(R0); | 353 __ Pop(R0); |
| 363 // Remove the stub frame. | 354 // Remove the stub frame. |
| 364 __ LeaveStubFrame(); | 355 __ LeaveStubFrame(); |
| 365 // Jump to the dart function. | 356 // Jump to the dart function. |
| 366 __ mov(CODE_REG, Operand(R0)); | 357 __ mov(CODE_REG, Operand(R0)); |
| 367 __ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); | 358 __ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); |
| 368 __ bx(R0); | 359 __ bx(R0); |
| 369 } | 360 } |
| 370 | 361 |
| 371 | |
| 372 // Input parameters: | 362 // Input parameters: |
| 373 // R2: smi-tagged argument count, may be zero. | 363 // R2: smi-tagged argument count, may be zero. |
| 374 // FP[kParamEndSlotFromFp + 1]: last argument. | 364 // FP[kParamEndSlotFromFp + 1]: last argument. |
| 375 static void PushArgumentsArray(Assembler* assembler) { | 365 static void PushArgumentsArray(Assembler* assembler) { |
| 376 // Allocate array to store arguments of caller. | 366 // Allocate array to store arguments of caller. |
| 377 __ LoadObject(R1, Object::null_object()); | 367 __ LoadObject(R1, Object::null_object()); |
| 378 // R1: null element type for raw Array. | 368 // R1: null element type for raw Array. |
| 379 // R2: smi-tagged argument count, may be zero. | 369 // R2: smi-tagged argument count, may be zero. |
| 380 __ BranchLink(*StubCode::AllocateArray_entry()); | 370 __ BranchLink(*StubCode::AllocateArray_entry()); |
| 381 // R0: newly allocated array. | 371 // R0: newly allocated array. |
| 382 // R2: smi-tagged argument count, may be zero (was preserved by the stub). | 372 // R2: smi-tagged argument count, may be zero (was preserved by the stub). |
| 383 __ Push(R0); // Array is in R0 and on top of stack. | 373 __ Push(R0); // Array is in R0 and on top of stack. |
| 384 __ AddImmediate(R1, FP, kParamEndSlotFromFp * kWordSize); | 374 __ AddImmediate(R1, FP, kParamEndSlotFromFp * kWordSize); |
| 385 __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag); | 375 __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag); |
| 386 // Copy arguments from stack to array (starting at the end). | 376 // Copy arguments from stack to array (starting at the end). |
| 387 // R1: address just beyond last argument on stack. | 377 // R1: address just beyond last argument on stack. |
| 388 // R3: address of first argument in array. | 378 // R3: address of first argument in array. |
| 389 Label enter; | 379 Label enter; |
| 390 __ b(&enter); | 380 __ b(&enter); |
| 391 Label loop; | 381 Label loop; |
| 392 __ Bind(&loop); | 382 __ Bind(&loop); |
| 393 __ ldr(IP, Address(R1, kWordSize, Address::PreIndex)); | 383 __ ldr(IP, Address(R1, kWordSize, Address::PreIndex)); |
| 394 // Generational barrier is needed, array is not necessarily in new space. | 384 // Generational barrier is needed, array is not necessarily in new space. |
| 395 __ StoreIntoObject(R0, Address(R3, R2, LSL, 1), IP); | 385 __ StoreIntoObject(R0, Address(R3, R2, LSL, 1), IP); |
| 396 __ Bind(&enter); | 386 __ Bind(&enter); |
| 397 __ subs(R2, R2, Operand(Smi::RawValue(1))); // R2 is Smi. | 387 __ subs(R2, R2, Operand(Smi::RawValue(1))); // R2 is Smi. |
| 398 __ b(&loop, PL); | 388 __ b(&loop, PL); |
| 399 } | 389 } |
| 400 | 390 |
| 401 | |
| 402 // Used by eager and lazy deoptimization. Preserve result in R0 if necessary. | 391 // Used by eager and lazy deoptimization. Preserve result in R0 if necessary. |
| 403 // This stub translates optimized frame into unoptimized frame. The optimized | 392 // This stub translates optimized frame into unoptimized frame. The optimized |
| 404 // frame can contain values in registers and on stack, the unoptimized | 393 // frame can contain values in registers and on stack, the unoptimized |
| 405 // frame contains all values on stack. | 394 // frame contains all values on stack. |
| 406 // Deoptimization occurs in following steps: | 395 // Deoptimization occurs in following steps: |
| 407 // - Push all registers that can contain values. | 396 // - Push all registers that can contain values. |
| 408 // - Call C routine to copy the stack and saved registers into temporary buffer. | 397 // - Call C routine to copy the stack and saved registers into temporary buffer. |
| 409 // - Adjust caller's frame to correct unoptimized frame size. | 398 // - Adjust caller's frame to correct unoptimized frame size. |
| 410 // - Fill the unoptimized frame. | 399 // - Fill the unoptimized frame. |
| 411 // - Materialize objects that require allocation (e.g. Double instances). | 400 // - Materialize objects that require allocation (e.g. Double instances). |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 } else if (kind == kLazyDeoptFromThrow) { | 537 } else if (kind == kLazyDeoptFromThrow) { |
| 549 __ Pop(R1); // Restore stacktrace. | 538 __ Pop(R1); // Restore stacktrace. |
| 550 __ Pop(R0); // Restore exception. | 539 __ Pop(R0); // Restore exception. |
| 551 } | 540 } |
| 552 __ LeaveStubFrame(); | 541 __ LeaveStubFrame(); |
| 553 // Remove materialization arguments. | 542 // Remove materialization arguments. |
| 554 __ add(SP, SP, Operand(R2, ASR, kSmiTagSize)); | 543 __ add(SP, SP, Operand(R2, ASR, kSmiTagSize)); |
| 555 // The caller is responsible for emitting the return instruction. | 544 // The caller is responsible for emitting the return instruction. |
| 556 } | 545 } |
| 557 | 546 |
| 558 | |
| 559 // R0: result, must be preserved | 547 // R0: result, must be preserved |
| 560 void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { | 548 void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { |
| 561 // Push zap value instead of CODE_REG for lazy deopt. | 549 // Push zap value instead of CODE_REG for lazy deopt. |
| 562 __ LoadImmediate(IP, kZapCodeReg); | 550 __ LoadImmediate(IP, kZapCodeReg); |
| 563 __ Push(IP); | 551 __ Push(IP); |
| 564 // Return address for "call" to deopt stub. | 552 // Return address for "call" to deopt stub. |
| 565 __ LoadImmediate(LR, kZapReturnAddress); | 553 __ LoadImmediate(LR, kZapReturnAddress); |
| 566 __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_return_stub_offset())); | 554 __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_return_stub_offset())); |
| 567 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn); | 555 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn); |
| 568 __ Ret(); | 556 __ Ret(); |
| 569 } | 557 } |
| 570 | 558 |
| 571 | |
| 572 // R0: exception, must be preserved | 559 // R0: exception, must be preserved |
| 573 // R1: stacktrace, must be preserved | 560 // R1: stacktrace, must be preserved |
| 574 void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) { | 561 void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) { |
| 575 // Push zap value instead of CODE_REG for lazy deopt. | 562 // Push zap value instead of CODE_REG for lazy deopt. |
| 576 __ LoadImmediate(IP, kZapCodeReg); | 563 __ LoadImmediate(IP, kZapCodeReg); |
| 577 __ Push(IP); | 564 __ Push(IP); |
| 578 // Return address for "call" to deopt stub. | 565 // Return address for "call" to deopt stub. |
| 579 __ LoadImmediate(LR, kZapReturnAddress); | 566 __ LoadImmediate(LR, kZapReturnAddress); |
| 580 __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_throw_stub_offset())); | 567 __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_throw_stub_offset())); |
| 581 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow); | 568 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow); |
| 582 __ Ret(); | 569 __ Ret(); |
| 583 } | 570 } |
| 584 | 571 |
| 585 | |
| 586 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 572 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
| 587 GenerateDeoptimizationSequence(assembler, kEagerDeopt); | 573 GenerateDeoptimizationSequence(assembler, kEagerDeopt); |
| 588 __ Ret(); | 574 __ Ret(); |
| 589 } | 575 } |
| 590 | 576 |
| 591 | |
| 592 static void GenerateDispatcherCode(Assembler* assembler, | 577 static void GenerateDispatcherCode(Assembler* assembler, |
| 593 Label* call_target_function) { | 578 Label* call_target_function) { |
| 594 __ Comment("NoSuchMethodDispatch"); | 579 __ Comment("NoSuchMethodDispatch"); |
| 595 // When lazily generated invocation dispatchers are disabled, the | 580 // When lazily generated invocation dispatchers are disabled, the |
| 596 // miss-handler may return null. | 581 // miss-handler may return null. |
| 597 __ CompareObject(R0, Object::null_object()); | 582 __ CompareObject(R0, Object::null_object()); |
| 598 __ b(call_target_function, NE); | 583 __ b(call_target_function, NE); |
| 599 __ EnterStubFrame(); | 584 __ EnterStubFrame(); |
| 600 // Load the receiver. | 585 // Load the receiver. |
| 601 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 586 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 615 // R2: Smi-tagged arguments array length. | 600 // R2: Smi-tagged arguments array length. |
| 616 PushArgumentsArray(assembler); | 601 PushArgumentsArray(assembler); |
| 617 const intptr_t kNumArgs = 4; | 602 const intptr_t kNumArgs = 4; |
| 618 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); | 603 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); |
| 619 __ Drop(4); | 604 __ Drop(4); |
| 620 __ Pop(R0); // Return value. | 605 __ Pop(R0); // Return value. |
| 621 __ LeaveStubFrame(); | 606 __ LeaveStubFrame(); |
| 622 __ Ret(); | 607 __ Ret(); |
| 623 } | 608 } |
| 624 | 609 |
| 625 | |
| 626 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { | 610 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { |
| 627 __ EnterStubFrame(); | 611 __ EnterStubFrame(); |
| 628 | 612 |
| 629 // Load the receiver. | 613 // Load the receiver. |
| 630 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 614 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
| 631 __ add(IP, FP, Operand(R2, LSL, 1)); // R2 is Smi. | 615 __ add(IP, FP, Operand(R2, LSL, 1)); // R2 is Smi. |
| 632 __ ldr(R8, Address(IP, kParamEndSlotFromFp * kWordSize)); | 616 __ ldr(R8, Address(IP, kParamEndSlotFromFp * kWordSize)); |
| 633 | 617 |
| 634 // Preserve IC data and arguments descriptor. | 618 // Preserve IC data and arguments descriptor. |
| 635 __ PushList((1 << R4) | (1 << R9)); | 619 __ PushList((1 << R4) | (1 << R9)); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 655 GenerateDispatcherCode(assembler, &call_target_function); | 639 GenerateDispatcherCode(assembler, &call_target_function); |
| 656 __ Bind(&call_target_function); | 640 __ Bind(&call_target_function); |
| 657 } | 641 } |
| 658 | 642 |
| 659 // Tail-call to target function. | 643 // Tail-call to target function. |
| 660 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 644 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
| 661 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); | 645 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
| 662 __ bx(R2); | 646 __ bx(R2); |
| 663 } | 647 } |
| 664 | 648 |
| 665 | |
| 666 // Called for inline allocation of arrays. | 649 // Called for inline allocation of arrays. |
| 667 // Input parameters: | 650 // Input parameters: |
| 668 // LR: return address. | 651 // LR: return address. |
| 669 // R1: array element type (either NULL or an instantiated type). | 652 // R1: array element type (either NULL or an instantiated type). |
| 670 // R2: array length as Smi (must be preserved). | 653 // R2: array length as Smi (must be preserved). |
| 671 // The newly allocated object is returned in R0. | 654 // The newly allocated object is returned in R0. |
| 672 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 655 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
| 673 Label slow_case; | 656 Label slow_case; |
| 674 // Compute the size to be allocated, it is based on the array length | 657 // Compute the size to be allocated, it is based on the array length |
| 675 // and is computed as: | 658 // and is computed as: |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 // Push array length as Smi and element type. | 761 // Push array length as Smi and element type. |
| 779 __ PushList((1 << R1) | (1 << R2) | (1 << IP)); | 762 __ PushList((1 << R1) | (1 << R2) | (1 << IP)); |
| 780 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); | 763 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); |
| 781 // Pop arguments; result is popped in IP. | 764 // Pop arguments; result is popped in IP. |
| 782 __ PopList((1 << R1) | (1 << R2) | (1 << IP)); // R2 is restored. | 765 __ PopList((1 << R1) | (1 << R2) | (1 << IP)); // R2 is restored. |
| 783 __ mov(R0, Operand(IP)); | 766 __ mov(R0, Operand(IP)); |
| 784 __ LeaveStubFrame(); | 767 __ LeaveStubFrame(); |
| 785 __ Ret(); | 768 __ Ret(); |
| 786 } | 769 } |
| 787 | 770 |
| 788 | |
| 789 // Called when invoking Dart code from C++ (VM code). | 771 // Called when invoking Dart code from C++ (VM code). |
| 790 // Input parameters: | 772 // Input parameters: |
| 791 // LR : points to return address. | 773 // LR : points to return address. |
| 792 // R0 : code object of the Dart function to call. | 774 // R0 : code object of the Dart function to call. |
| 793 // R1 : arguments descriptor array. | 775 // R1 : arguments descriptor array. |
| 794 // R2 : arguments array. | 776 // R2 : arguments array. |
| 795 // R3 : current thread. | 777 // R3 : current thread. |
| 796 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { | 778 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
| 797 // Save frame pointer coming in. | 779 // Save frame pointer coming in. |
| 798 __ EnterFrame((1 << FP) | (1 << LR), 0); | 780 __ EnterFrame((1 << FP) | (1 << LR), 0); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 899 } | 881 } |
| 900 // Restore CPU registers. | 882 // Restore CPU registers. |
| 901 __ PopList(kAbiPreservedCpuRegs); | 883 __ PopList(kAbiPreservedCpuRegs); |
| 902 __ set_constant_pool_allowed(false); | 884 __ set_constant_pool_allowed(false); |
| 903 | 885 |
| 904 // Restore the frame pointer and return. | 886 // Restore the frame pointer and return. |
| 905 __ LeaveFrame((1 << FP) | (1 << LR)); | 887 __ LeaveFrame((1 << FP) | (1 << LR)); |
| 906 __ Ret(); | 888 __ Ret(); |
| 907 } | 889 } |
| 908 | 890 |
| 909 | |
| 910 // Called for inline allocation of contexts. | 891 // Called for inline allocation of contexts. |
| 911 // Input: | 892 // Input: |
| 912 // R1: number of context variables. | 893 // R1: number of context variables. |
| 913 // Output: | 894 // Output: |
| 914 // R0: new allocated RawContext object. | 895 // R0: new allocated RawContext object. |
| 915 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 896 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
| 916 if (FLAG_inline_alloc) { | 897 if (FLAG_inline_alloc) { |
| 917 Label slow_case; | 898 Label slow_case; |
| 918 // First compute the rounded instance size. | 899 // First compute the rounded instance size. |
| 919 // R1: number of context variables. | 900 // R1: number of context variables. |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1021 __ PushList((1 << R1) | (1 << R2)); | 1002 __ PushList((1 << R1) | (1 << R2)); |
| 1022 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context. | 1003 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context. |
| 1023 __ Drop(1); // Pop number of context variables argument. | 1004 __ Drop(1); // Pop number of context variables argument. |
| 1024 __ Pop(R0); // Pop the new context object. | 1005 __ Pop(R0); // Pop the new context object. |
| 1025 // R0: new object | 1006 // R0: new object |
| 1026 // Restore the frame pointer. | 1007 // Restore the frame pointer. |
| 1027 __ LeaveStubFrame(); | 1008 __ LeaveStubFrame(); |
| 1028 __ Ret(); | 1009 __ Ret(); |
| 1029 } | 1010 } |
| 1030 | 1011 |
| 1031 | |
| 1032 // Helper stub to implement Assembler::StoreIntoObject. | 1012 // Helper stub to implement Assembler::StoreIntoObject. |
| 1033 // Input parameters: | 1013 // Input parameters: |
| 1034 // R0: address (i.e. object) being stored into. | 1014 // R0: address (i.e. object) being stored into. |
| 1035 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { | 1015 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { |
| 1036 // Save values being destroyed. | 1016 // Save values being destroyed. |
| 1037 __ PushList((1 << R1) | (1 << R2) | (1 << R3)); | 1017 __ PushList((1 << R1) | (1 << R2) | (1 << R3)); |
| 1038 | 1018 |
| 1039 Label add_to_buffer; | 1019 Label add_to_buffer; |
| 1040 // Check whether this object has already been remembered. Skip adding to the | 1020 // Check whether this object has already been remembered. Skip adding to the |
| 1041 // store buffer if the object is in the store buffer already. | 1021 // store buffer if the object is in the store buffer already. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1094 // Setup frame, push callee-saved registers. | 1074 // Setup frame, push callee-saved registers. |
| 1095 | 1075 |
| 1096 __ EnterCallRuntimeFrame(0 * kWordSize); | 1076 __ EnterCallRuntimeFrame(0 * kWordSize); |
| 1097 __ mov(R0, Operand(THR)); | 1077 __ mov(R0, Operand(THR)); |
| 1098 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); | 1078 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); |
| 1099 // Restore callee-saved registers, tear down frame. | 1079 // Restore callee-saved registers, tear down frame. |
| 1100 __ LeaveCallRuntimeFrame(); | 1080 __ LeaveCallRuntimeFrame(); |
| 1101 __ Ret(); | 1081 __ Ret(); |
| 1102 } | 1082 } |
| 1103 | 1083 |
| 1104 | |
| 1105 // Called for inline allocation of objects. | 1084 // Called for inline allocation of objects. |
| 1106 // Input parameters: | 1085 // Input parameters: |
| 1107 // LR : return address. | 1086 // LR : return address. |
| 1108 // SP + 0 : type arguments object (only if class is parameterized). | 1087 // SP + 0 : type arguments object (only if class is parameterized). |
| 1109 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, | 1088 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, |
| 1110 const Class& cls) { | 1089 const Class& cls) { |
| 1111 // Must load pool pointer before being able to patch. | 1090 // Must load pool pointer before being able to patch. |
| 1112 Register new_pp = NOTFP; | 1091 Register new_pp = NOTFP; |
| 1113 __ LoadPoolPointer(new_pp); | 1092 __ LoadPoolPointer(new_pp); |
| 1114 // The generated code is different if the class is parameterized. | 1093 // The generated code is different if the class is parameterized. |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1231 } | 1210 } |
| 1232 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. | 1211 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. |
| 1233 __ Drop(2); // Pop arguments. | 1212 __ Drop(2); // Pop arguments. |
| 1234 __ Pop(R0); // Pop result (newly allocated object). | 1213 __ Pop(R0); // Pop result (newly allocated object). |
| 1235 // R0: new object | 1214 // R0: new object |
| 1236 // Restore the frame pointer. | 1215 // Restore the frame pointer. |
| 1237 __ LeaveStubFrame(); | 1216 __ LeaveStubFrame(); |
| 1238 __ Ret(); | 1217 __ Ret(); |
| 1239 } | 1218 } |
| 1240 | 1219 |
| 1241 | |
| 1242 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function | 1220 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function |
| 1243 // from the entry code of a dart function after an error in passed argument | 1221 // from the entry code of a dart function after an error in passed argument |
| 1244 // name or number is detected. | 1222 // name or number is detected. |
| 1245 // Input parameters: | 1223 // Input parameters: |
| 1246 // LR : return address. | 1224 // LR : return address. |
| 1247 // SP : address of last argument. | 1225 // SP : address of last argument. |
| 1248 // R4: arguments descriptor array. | 1226 // R4: arguments descriptor array. |
| 1249 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) { | 1227 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) { |
| 1250 __ EnterStubFrame(); | 1228 __ EnterStubFrame(); |
| 1251 | 1229 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1267 | 1245 |
| 1268 // R2: Smi-tagged arguments array length. | 1246 // R2: Smi-tagged arguments array length. |
| 1269 PushArgumentsArray(assembler); | 1247 PushArgumentsArray(assembler); |
| 1270 | 1248 |
| 1271 const intptr_t kNumArgs = 3; | 1249 const intptr_t kNumArgs = 3; |
| 1272 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs); | 1250 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs); |
| 1273 // noSuchMethod on closures always throws an error, so it will never return. | 1251 // noSuchMethod on closures always throws an error, so it will never return. |
| 1274 __ bkpt(0); | 1252 __ bkpt(0); |
| 1275 } | 1253 } |
| 1276 | 1254 |
| 1277 | |
| 1278 // R8: function object. | 1255 // R8: function object. |
| 1279 // R9: inline cache data object. | 1256 // R9: inline cache data object. |
| 1280 // Cannot use function object from ICData as it may be the inlined | 1257 // Cannot use function object from ICData as it may be the inlined |
| 1281 // function and not the top-scope function. | 1258 // function and not the top-scope function. |
| 1282 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { | 1259 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { |
| 1283 Register ic_reg = R9; | 1260 Register ic_reg = R9; |
| 1284 Register func_reg = R8; | 1261 Register func_reg = R8; |
| 1285 if (FLAG_trace_optimized_ic_calls) { | 1262 if (FLAG_trace_optimized_ic_calls) { |
| 1286 __ EnterStubFrame(); | 1263 __ EnterStubFrame(); |
| 1287 __ PushList((1 << R9) | (1 << R8)); // Preserve. | 1264 __ PushList((1 << R9) | (1 << R8)); // Preserve. |
| 1288 __ Push(ic_reg); // Argument. | 1265 __ Push(ic_reg); // Argument. |
| 1289 __ Push(func_reg); // Argument. | 1266 __ Push(func_reg); // Argument. |
| 1290 __ CallRuntime(kTraceICCallRuntimeEntry, 2); | 1267 __ CallRuntime(kTraceICCallRuntimeEntry, 2); |
| 1291 __ Drop(2); // Discard argument; | 1268 __ Drop(2); // Discard argument; |
| 1292 __ PopList((1 << R9) | (1 << R8)); // Restore. | 1269 __ PopList((1 << R9) | (1 << R8)); // Restore. |
| 1293 __ LeaveStubFrame(); | 1270 __ LeaveStubFrame(); |
| 1294 } | 1271 } |
| 1295 __ ldr(NOTFP, FieldAddress(func_reg, Function::usage_counter_offset())); | 1272 __ ldr(NOTFP, FieldAddress(func_reg, Function::usage_counter_offset())); |
| 1296 __ add(NOTFP, NOTFP, Operand(1)); | 1273 __ add(NOTFP, NOTFP, Operand(1)); |
| 1297 __ str(NOTFP, FieldAddress(func_reg, Function::usage_counter_offset())); | 1274 __ str(NOTFP, FieldAddress(func_reg, Function::usage_counter_offset())); |
| 1298 } | 1275 } |
| 1299 | 1276 |
| 1300 | |
| 1301 // Loads function into 'temp_reg'. | 1277 // Loads function into 'temp_reg'. |
| 1302 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, | 1278 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, |
| 1303 Register temp_reg) { | 1279 Register temp_reg) { |
| 1304 if (FLAG_optimization_counter_threshold >= 0) { | 1280 if (FLAG_optimization_counter_threshold >= 0) { |
| 1305 Register ic_reg = R9; | 1281 Register ic_reg = R9; |
| 1306 Register func_reg = temp_reg; | 1282 Register func_reg = temp_reg; |
| 1307 ASSERT(temp_reg == R8); | 1283 ASSERT(temp_reg == R8); |
| 1308 __ Comment("Increment function counter"); | 1284 __ Comment("Increment function counter"); |
| 1309 __ ldr(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); | 1285 __ ldr(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); |
| 1310 __ ldr(NOTFP, FieldAddress(func_reg, Function::usage_counter_offset())); | 1286 __ ldr(NOTFP, FieldAddress(func_reg, Function::usage_counter_offset())); |
| 1311 __ add(NOTFP, NOTFP, Operand(1)); | 1287 __ add(NOTFP, NOTFP, Operand(1)); |
| 1312 __ str(NOTFP, FieldAddress(func_reg, Function::usage_counter_offset())); | 1288 __ str(NOTFP, FieldAddress(func_reg, Function::usage_counter_offset())); |
| 1313 } | 1289 } |
| 1314 } | 1290 } |
| 1315 | 1291 |
| 1316 | |
| 1317 // Note: R9 must be preserved. | 1292 // Note: R9 must be preserved. |
| 1318 // Attempt a quick Smi operation for known operations ('kind'). The ICData | 1293 // Attempt a quick Smi operation for known operations ('kind'). The ICData |
| 1319 // must have been primed with a Smi/Smi check that will be used for counting | 1294 // must have been primed with a Smi/Smi check that will be used for counting |
| 1320 // the invocations. | 1295 // the invocations. |
| 1321 static void EmitFastSmiOp(Assembler* assembler, | 1296 static void EmitFastSmiOp(Assembler* assembler, |
| 1322 Token::Kind kind, | 1297 Token::Kind kind, |
| 1323 intptr_t num_args, | 1298 intptr_t num_args, |
| 1324 Label* not_smi_or_overflow) { | 1299 Label* not_smi_or_overflow) { |
| 1325 __ Comment("Fast Smi op"); | 1300 __ Comment("Fast Smi op"); |
| 1326 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1301 __ ldr(R0, Address(SP, 0 * kWordSize)); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1370 if (FLAG_optimization_counter_threshold >= 0) { | 1345 if (FLAG_optimization_counter_threshold >= 0) { |
| 1371 // Update counter, ignore overflow. | 1346 // Update counter, ignore overflow. |
| 1372 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1347 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1373 __ LoadFromOffset(kWord, R1, R8, count_offset); | 1348 __ LoadFromOffset(kWord, R1, R8, count_offset); |
| 1374 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1349 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
| 1375 __ StoreIntoSmiField(Address(R8, count_offset), R1); | 1350 __ StoreIntoSmiField(Address(R8, count_offset), R1); |
| 1376 } | 1351 } |
| 1377 __ Ret(); | 1352 __ Ret(); |
| 1378 } | 1353 } |
| 1379 | 1354 |
| 1380 | |
| 1381 // Generate inline cache check for 'num_args'. | 1355 // Generate inline cache check for 'num_args'. |
| 1382 // LR: return address. | 1356 // LR: return address. |
| 1383 // R9: inline cache data object. | 1357 // R9: inline cache data object. |
| 1384 // Control flow: | 1358 // Control flow: |
| 1385 // - If receiver is null -> jump to IC miss. | 1359 // - If receiver is null -> jump to IC miss. |
| 1386 // - If receiver is Smi -> load Smi class. | 1360 // - If receiver is Smi -> load Smi class. |
| 1387 // - If receiver is not-Smi -> load receiver's class. | 1361 // - If receiver is not-Smi -> load receiver's class. |
| 1388 // - Check if 'num_args' (including receiver) match any IC data group. | 1362 // - Check if 'num_args' (including receiver) match any IC data group. |
| 1389 // - Match found -> jump to target. | 1363 // - Match found -> jump to target. |
| 1390 // - Match not found -> jump to IC miss. | 1364 // - Match not found -> jump to IC miss. |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1545 __ EnterStubFrame(); | 1519 __ EnterStubFrame(); |
| 1546 __ Push(R9); // Preserve IC data. | 1520 __ Push(R9); // Preserve IC data. |
| 1547 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1521 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1548 __ Pop(R9); | 1522 __ Pop(R9); |
| 1549 __ RestoreCodePointer(); | 1523 __ RestoreCodePointer(); |
| 1550 __ LeaveStubFrame(); | 1524 __ LeaveStubFrame(); |
| 1551 __ b(&done_stepping); | 1525 __ b(&done_stepping); |
| 1552 } | 1526 } |
| 1553 } | 1527 } |
| 1554 | 1528 |
| 1555 | |
| 1556 // Use inline cache data array to invoke the target or continue in inline | 1529 // Use inline cache data array to invoke the target or continue in inline |
| 1557 // cache miss handler. Stub for 1-argument check (receiver class). | 1530 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1558 // LR: return address. | 1531 // LR: return address. |
| 1559 // R9: inline cache data object. | 1532 // R9: inline cache data object. |
| 1560 // Inline cache data object structure: | 1533 // Inline cache data object structure: |
| 1561 // 0: function-name | 1534 // 0: function-name |
| 1562 // 1: N, number of arguments checked. | 1535 // 1: N, number of arguments checked. |
| 1563 // 2 .. (length - 1): group of checks, each check containing: | 1536 // 2 .. (length - 1): group of checks, each check containing: |
| 1564 // - N classes. | 1537 // - N classes. |
| 1565 // - 1 target function. | 1538 // - 1 target function. |
| 1566 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1539 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
| 1567 GenerateUsageCounterIncrement(assembler, R8); | 1540 GenerateUsageCounterIncrement(assembler, R8); |
| 1568 GenerateNArgsCheckInlineCacheStub( | 1541 GenerateNArgsCheckInlineCacheStub( |
| 1569 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); | 1542 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); |
| 1570 } | 1543 } |
| 1571 | 1544 |
| 1572 | |
| 1573 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1545 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
| 1574 GenerateUsageCounterIncrement(assembler, R8); | 1546 GenerateUsageCounterIncrement(assembler, R8); |
| 1575 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1547 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
| 1576 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1548 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
| 1577 Token::kILLEGAL); | 1549 Token::kILLEGAL); |
| 1578 } | 1550 } |
| 1579 | 1551 |
| 1580 | |
| 1581 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { | 1552 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { |
| 1582 GenerateUsageCounterIncrement(assembler, R8); | 1553 GenerateUsageCounterIncrement(assembler, R8); |
| 1583 GenerateNArgsCheckInlineCacheStub( | 1554 GenerateNArgsCheckInlineCacheStub( |
| 1584 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD); | 1555 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD); |
| 1585 } | 1556 } |
| 1586 | 1557 |
| 1587 | |
| 1588 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { | 1558 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { |
| 1589 GenerateUsageCounterIncrement(assembler, R8); | 1559 GenerateUsageCounterIncrement(assembler, R8); |
| 1590 GenerateNArgsCheckInlineCacheStub( | 1560 GenerateNArgsCheckInlineCacheStub( |
| 1591 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB); | 1561 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB); |
| 1592 } | 1562 } |
| 1593 | 1563 |
| 1594 | |
| 1595 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { | 1564 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { |
| 1596 GenerateUsageCounterIncrement(assembler, R8); | 1565 GenerateUsageCounterIncrement(assembler, R8); |
| 1597 GenerateNArgsCheckInlineCacheStub( | 1566 GenerateNArgsCheckInlineCacheStub( |
| 1598 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ); | 1567 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ); |
| 1599 } | 1568 } |
| 1600 | 1569 |
| 1601 | |
| 1602 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( | 1570 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( |
| 1603 Assembler* assembler) { | 1571 Assembler* assembler) { |
| 1604 GenerateOptimizedUsageCounterIncrement(assembler); | 1572 GenerateOptimizedUsageCounterIncrement(assembler); |
| 1605 GenerateNArgsCheckInlineCacheStub(assembler, 1, | 1573 GenerateNArgsCheckInlineCacheStub(assembler, 1, |
| 1606 kInlineCacheMissHandlerOneArgRuntimeEntry, | 1574 kInlineCacheMissHandlerOneArgRuntimeEntry, |
| 1607 Token::kILLEGAL, true /* optimized */); | 1575 Token::kILLEGAL, true /* optimized */); |
| 1608 } | 1576 } |
| 1609 | 1577 |
| 1610 | |
| 1611 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( | 1578 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( |
| 1612 Assembler* assembler) { | 1579 Assembler* assembler) { |
| 1613 GenerateOptimizedUsageCounterIncrement(assembler); | 1580 GenerateOptimizedUsageCounterIncrement(assembler); |
| 1614 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1581 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
| 1615 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1582 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
| 1616 Token::kILLEGAL, true /* optimized */); | 1583 Token::kILLEGAL, true /* optimized */); |
| 1617 } | 1584 } |
| 1618 | 1585 |
| 1619 | |
| 1620 // Intermediary stub between a static call and its target. ICData contains | 1586 // Intermediary stub between a static call and its target. ICData contains |
| 1621 // the target function and the call count. | 1587 // the target function and the call count. |
| 1622 // R9: ICData | 1588 // R9: ICData |
| 1623 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1589 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1624 GenerateUsageCounterIncrement(assembler, R8); | 1590 GenerateUsageCounterIncrement(assembler, R8); |
| 1625 #if defined(DEBUG) | 1591 #if defined(DEBUG) |
| 1626 { | 1592 { |
| 1627 Label ok; | 1593 Label ok; |
| 1628 // Check that the IC data array has NumArgsTested() == 0. | 1594 // Check that the IC data array has NumArgsTested() == 0. |
| 1629 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. | 1595 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1676 __ EnterStubFrame(); | 1642 __ EnterStubFrame(); |
| 1677 __ Push(R9); // Preserve IC data. | 1643 __ Push(R9); // Preserve IC data. |
| 1678 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1644 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1679 __ Pop(R9); | 1645 __ Pop(R9); |
| 1680 __ RestoreCodePointer(); | 1646 __ RestoreCodePointer(); |
| 1681 __ LeaveStubFrame(); | 1647 __ LeaveStubFrame(); |
| 1682 __ b(&done_stepping); | 1648 __ b(&done_stepping); |
| 1683 } | 1649 } |
| 1684 } | 1650 } |
| 1685 | 1651 |
| 1686 | |
| 1687 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { | 1652 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1688 GenerateUsageCounterIncrement(assembler, R8); | 1653 GenerateUsageCounterIncrement(assembler, R8); |
| 1689 GenerateNArgsCheckInlineCacheStub( | 1654 GenerateNArgsCheckInlineCacheStub( |
| 1690 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); | 1655 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); |
| 1691 } | 1656 } |
| 1692 | 1657 |
| 1693 | |
| 1694 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1658 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1695 GenerateUsageCounterIncrement(assembler, R8); | 1659 GenerateUsageCounterIncrement(assembler, R8); |
| 1696 GenerateNArgsCheckInlineCacheStub( | 1660 GenerateNArgsCheckInlineCacheStub( |
| 1697 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); | 1661 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); |
| 1698 } | 1662 } |
| 1699 | 1663 |
| 1700 | |
| 1701 // Stub for compiling a function and jumping to the compiled code. | 1664 // Stub for compiling a function and jumping to the compiled code. |
| 1702 // R9: IC-Data (for methods). | 1665 // R9: IC-Data (for methods). |
| 1703 // R4: Arguments descriptor. | 1666 // R4: Arguments descriptor. |
| 1704 // R0: Function. | 1667 // R0: Function. |
| 1705 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { | 1668 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { |
| 1706 // Preserve arg desc. and IC data object. | 1669 // Preserve arg desc. and IC data object. |
| 1707 __ EnterStubFrame(); | 1670 __ EnterStubFrame(); |
| 1708 __ PushList((1 << R4) | (1 << R9)); | 1671 __ PushList((1 << R4) | (1 << R9)); |
| 1709 __ Push(R0); // Pass function. | 1672 __ Push(R0); // Pass function. |
| 1710 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | 1673 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
| 1711 __ Pop(R0); // Restore argument. | 1674 __ Pop(R0); // Restore argument. |
| 1712 __ PopList((1 << R4) | (1 << R9)); // Restore arg desc. and IC data. | 1675 __ PopList((1 << R4) | (1 << R9)); // Restore arg desc. and IC data. |
| 1713 __ LeaveStubFrame(); | 1676 __ LeaveStubFrame(); |
| 1714 | 1677 |
| 1715 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 1678 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
| 1716 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); | 1679 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
| 1717 __ bx(R2); | 1680 __ bx(R2); |
| 1718 } | 1681 } |
| 1719 | 1682 |
| 1720 | |
| 1721 // R9: Contains an ICData. | 1683 // R9: Contains an ICData. |
| 1722 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { | 1684 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { |
| 1723 __ EnterStubFrame(); | 1685 __ EnterStubFrame(); |
| 1724 __ LoadImmediate(R0, 0); | 1686 __ LoadImmediate(R0, 0); |
| 1725 // Preserve arguments descriptor and make room for result. | 1687 // Preserve arguments descriptor and make room for result. |
| 1726 __ PushList((1 << R0) | (1 << R9)); | 1688 __ PushList((1 << R0) | (1 << R9)); |
| 1727 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1689 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
| 1728 __ PopList((1 << R0) | (1 << R9)); | 1690 __ PopList((1 << R0) | (1 << R9)); |
| 1729 __ LeaveStubFrame(); | 1691 __ LeaveStubFrame(); |
| 1730 __ mov(CODE_REG, Operand(R0)); | 1692 __ mov(CODE_REG, Operand(R0)); |
| 1731 __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset())); | 1693 __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset())); |
| 1732 __ bx(R0); | 1694 __ bx(R0); |
| 1733 } | 1695 } |
| 1734 | 1696 |
| 1735 | |
| 1736 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { | 1697 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { |
| 1737 __ EnterStubFrame(); | 1698 __ EnterStubFrame(); |
| 1738 __ LoadImmediate(R0, 0); | 1699 __ LoadImmediate(R0, 0); |
| 1739 // Make room for result. | 1700 // Make room for result. |
| 1740 __ PushList((1 << R0)); | 1701 __ PushList((1 << R0)); |
| 1741 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1702 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
| 1742 __ PopList((1 << CODE_REG)); | 1703 __ PopList((1 << CODE_REG)); |
| 1743 __ LeaveStubFrame(); | 1704 __ LeaveStubFrame(); |
| 1744 __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset())); | 1705 __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset())); |
| 1745 __ bx(R0); | 1706 __ bx(R0); |
| 1746 } | 1707 } |
| 1747 | 1708 |
| 1748 | |
| 1749 // Called only from unoptimized code. All relevant registers have been saved. | 1709 // Called only from unoptimized code. All relevant registers have been saved. |
| 1750 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { | 1710 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { |
| 1751 // Check single stepping. | 1711 // Check single stepping. |
| 1752 Label stepping, done_stepping; | 1712 Label stepping, done_stepping; |
| 1753 __ LoadIsolate(R1); | 1713 __ LoadIsolate(R1); |
| 1754 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); | 1714 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); |
| 1755 __ CompareImmediate(R1, 0); | 1715 __ CompareImmediate(R1, 0); |
| 1756 __ b(&stepping, NE); | 1716 __ b(&stepping, NE); |
| 1757 __ Bind(&done_stepping); | 1717 __ Bind(&done_stepping); |
| 1758 __ Ret(); | 1718 __ Ret(); |
| 1759 | 1719 |
| 1760 __ Bind(&stepping); | 1720 __ Bind(&stepping); |
| 1761 __ EnterStubFrame(); | 1721 __ EnterStubFrame(); |
| 1762 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1722 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1763 __ LeaveStubFrame(); | 1723 __ LeaveStubFrame(); |
| 1764 __ b(&done_stepping); | 1724 __ b(&done_stepping); |
| 1765 } | 1725 } |
| 1766 | 1726 |
| 1767 | |
| 1768 // Used to check class and type arguments. Arguments passed in registers: | 1727 // Used to check class and type arguments. Arguments passed in registers: |
| 1769 // LR: return address. | 1728 // LR: return address. |
| 1770 // R0: instance (must be preserved). | 1729 // R0: instance (must be preserved). |
| 1771 // R2: instantiator type arguments (only if n == 4, can be raw_null). | 1730 // R2: instantiator type arguments (only if n == 4, can be raw_null). |
| 1772 // R1: function type arguments (only if n == 4, can be raw_null). | 1731 // R1: function type arguments (only if n == 4, can be raw_null). |
| 1773 // R3: SubtypeTestCache. | 1732 // R3: SubtypeTestCache. |
| 1774 // Result in R1: null -> not found, otherwise result (true or false). | 1733 // Result in R1: null -> not found, otherwise result (true or false). |
| 1775 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1734 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
| 1776 ASSERT((n == 1) || (n == 2) || (n == 4)); | 1735 ASSERT((n == 1) || (n == 2) || (n == 4)); |
| 1777 if (n > 1) { | 1736 if (n > 1) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1843 // Fall through to not found. | 1802 // Fall through to not found. |
| 1844 __ Bind(¬_found); | 1803 __ Bind(¬_found); |
| 1845 __ LoadObject(R1, Object::null_object()); | 1804 __ LoadObject(R1, Object::null_object()); |
| 1846 __ Ret(); | 1805 __ Ret(); |
| 1847 | 1806 |
| 1848 __ Bind(&found); | 1807 __ Bind(&found); |
| 1849 __ ldr(R1, Address(R3, kWordSize * SubtypeTestCache::kTestResult)); | 1808 __ ldr(R1, Address(R3, kWordSize * SubtypeTestCache::kTestResult)); |
| 1850 __ Ret(); | 1809 __ Ret(); |
| 1851 } | 1810 } |
| 1852 | 1811 |
| 1853 | |
| 1854 // Used to check class and type arguments. Arguments passed in registers: | 1812 // Used to check class and type arguments. Arguments passed in registers: |
| 1855 // LR: return address. | 1813 // LR: return address. |
| 1856 // R0: instance (must be preserved). | 1814 // R0: instance (must be preserved). |
| 1857 // R2: unused. | 1815 // R2: unused. |
| 1858 // R1: unused. | 1816 // R1: unused. |
| 1859 // R3: SubtypeTestCache. | 1817 // R3: SubtypeTestCache. |
| 1860 // Result in R1: null -> not found, otherwise result (true or false). | 1818 // Result in R1: null -> not found, otherwise result (true or false). |
| 1861 void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) { | 1819 void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) { |
| 1862 GenerateSubtypeNTestCacheStub(assembler, 1); | 1820 GenerateSubtypeNTestCacheStub(assembler, 1); |
| 1863 } | 1821 } |
| 1864 | 1822 |
| 1865 | |
| 1866 // Used to check class and type arguments. Arguments passed in registers: | 1823 // Used to check class and type arguments. Arguments passed in registers: |
| 1867 // LR: return address. | 1824 // LR: return address. |
| 1868 // R0: instance (must be preserved). | 1825 // R0: instance (must be preserved). |
| 1869 // R2: unused. | 1826 // R2: unused. |
| 1870 // R1: unused. | 1827 // R1: unused. |
| 1871 // R3: SubtypeTestCache. | 1828 // R3: SubtypeTestCache. |
| 1872 // Result in R1: null -> not found, otherwise result (true or false). | 1829 // Result in R1: null -> not found, otherwise result (true or false). |
| 1873 void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) { | 1830 void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) { |
| 1874 GenerateSubtypeNTestCacheStub(assembler, 2); | 1831 GenerateSubtypeNTestCacheStub(assembler, 2); |
| 1875 } | 1832 } |
| 1876 | 1833 |
| 1877 | |
| 1878 // Used to check class and type arguments. Arguments passed in registers: | 1834 // Used to check class and type arguments. Arguments passed in registers: |
| 1879 // LR: return address. | 1835 // LR: return address. |
| 1880 // R0: instance (must be preserved). | 1836 // R0: instance (must be preserved). |
| 1881 // R2: instantiator type arguments (can be raw_null). | 1837 // R2: instantiator type arguments (can be raw_null). |
| 1882 // R1: function type arguments (can be raw_null). | 1838 // R1: function type arguments (can be raw_null). |
| 1883 // R3: SubtypeTestCache. | 1839 // R3: SubtypeTestCache. |
| 1884 // Result in R1: null -> not found, otherwise result (true or false). | 1840 // Result in R1: null -> not found, otherwise result (true or false). |
| 1885 void StubCode::GenerateSubtype4TestCacheStub(Assembler* assembler) { | 1841 void StubCode::GenerateSubtype4TestCacheStub(Assembler* assembler) { |
| 1886 GenerateSubtypeNTestCacheStub(assembler, 4); | 1842 GenerateSubtypeNTestCacheStub(assembler, 4); |
| 1887 } | 1843 } |
| 1888 | 1844 |
| 1889 | |
| 1890 // Return the current stack pointer address, used to do stack alignment checks. | 1845 // Return the current stack pointer address, used to do stack alignment checks. |
| 1891 void StubCode::GenerateGetCStackPointerStub(Assembler* assembler) { | 1846 void StubCode::GenerateGetCStackPointerStub(Assembler* assembler) { |
| 1892 __ mov(R0, Operand(SP)); | 1847 __ mov(R0, Operand(SP)); |
| 1893 __ Ret(); | 1848 __ Ret(); |
| 1894 } | 1849 } |
| 1895 | 1850 |
| 1896 | |
| 1897 // Jump to a frame on the call stack. | 1851 // Jump to a frame on the call stack. |
| 1898 // LR: return address. | 1852 // LR: return address. |
| 1899 // R0: program_counter. | 1853 // R0: program_counter. |
| 1900 // R1: stack_pointer. | 1854 // R1: stack_pointer. |
| 1901 // R2: frame_pointer. | 1855 // R2: frame_pointer. |
| 1902 // R3: thread. | 1856 // R3: thread. |
| 1903 // Does not return. | 1857 // Does not return. |
| 1904 void StubCode::GenerateJumpToFrameStub(Assembler* assembler) { | 1858 void StubCode::GenerateJumpToFrameStub(Assembler* assembler) { |
| 1905 ASSERT(kExceptionObjectReg == R0); | 1859 ASSERT(kExceptionObjectReg == R0); |
| 1906 ASSERT(kStackTraceObjectReg == R1); | 1860 ASSERT(kStackTraceObjectReg == R1); |
| 1907 __ mov(IP, Operand(R1)); // Copy Stack pointer into IP. | 1861 __ mov(IP, Operand(R1)); // Copy Stack pointer into IP. |
| 1908 __ mov(LR, Operand(R0)); // Program counter. | 1862 __ mov(LR, Operand(R0)); // Program counter. |
| 1909 __ mov(THR, Operand(R3)); // Thread. | 1863 __ mov(THR, Operand(R3)); // Thread. |
| 1910 __ mov(FP, Operand(R2)); // Frame_pointer. | 1864 __ mov(FP, Operand(R2)); // Frame_pointer. |
| 1911 __ mov(SP, Operand(IP)); // Set Stack pointer. | 1865 __ mov(SP, Operand(IP)); // Set Stack pointer. |
| 1912 // Set the tag. | 1866 // Set the tag. |
| 1913 __ LoadImmediate(R2, VMTag::kDartTagId); | 1867 __ LoadImmediate(R2, VMTag::kDartTagId); |
| 1914 __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset()); | 1868 __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset()); |
| 1915 // Clear top exit frame. | 1869 // Clear top exit frame. |
| 1916 __ LoadImmediate(R2, 0); | 1870 __ LoadImmediate(R2, 0); |
| 1917 __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset()); | 1871 __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset()); |
| 1918 // Restore the pool pointer. | 1872 // Restore the pool pointer. |
| 1919 __ RestoreCodePointer(); | 1873 __ RestoreCodePointer(); |
| 1920 __ LoadPoolPointer(); | 1874 __ LoadPoolPointer(); |
| 1921 __ bx(LR); // Jump to continuation point. | 1875 __ bx(LR); // Jump to continuation point. |
| 1922 } | 1876 } |
| 1923 | 1877 |
| 1924 | |
| 1925 // Run an exception handler. Execution comes from JumpToFrame | 1878 // Run an exception handler. Execution comes from JumpToFrame |
| 1926 // stub or from the simulator. | 1879 // stub or from the simulator. |
| 1927 // | 1880 // |
| 1928 // The arguments are stored in the Thread object. | 1881 // The arguments are stored in the Thread object. |
| 1929 // Does not return. | 1882 // Does not return. |
| 1930 void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) { | 1883 void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) { |
| 1931 __ LoadFromOffset(kWord, LR, THR, Thread::resume_pc_offset()); | 1884 __ LoadFromOffset(kWord, LR, THR, Thread::resume_pc_offset()); |
| 1932 __ LoadImmediate(R2, 0); | 1885 __ LoadImmediate(R2, 0); |
| 1933 | 1886 |
| 1934 // Exception object. | 1887 // Exception object. |
| 1935 __ LoadFromOffset(kWord, R0, THR, Thread::active_exception_offset()); | 1888 __ LoadFromOffset(kWord, R0, THR, Thread::active_exception_offset()); |
| 1936 __ StoreToOffset(kWord, R2, THR, Thread::active_exception_offset()); | 1889 __ StoreToOffset(kWord, R2, THR, Thread::active_exception_offset()); |
| 1937 | 1890 |
| 1938 // StackTrace object. | 1891 // StackTrace object. |
| 1939 __ LoadFromOffset(kWord, R1, THR, Thread::active_stacktrace_offset()); | 1892 __ LoadFromOffset(kWord, R1, THR, Thread::active_stacktrace_offset()); |
| 1940 __ StoreToOffset(kWord, R2, THR, Thread::active_stacktrace_offset()); | 1893 __ StoreToOffset(kWord, R2, THR, Thread::active_stacktrace_offset()); |
| 1941 | 1894 |
| 1942 __ bx(LR); // Jump to the exception handler code. | 1895 __ bx(LR); // Jump to the exception handler code. |
| 1943 } | 1896 } |
| 1944 | 1897 |
| 1945 | |
| 1946 // Deoptimize a frame on the call stack before rewinding. | 1898 // Deoptimize a frame on the call stack before rewinding. |
| 1947 // The arguments are stored in the Thread object. | 1899 // The arguments are stored in the Thread object. |
| 1948 // No result. | 1900 // No result. |
| 1949 void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) { | 1901 void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) { |
| 1950 // Push zap value instead of CODE_REG. | 1902 // Push zap value instead of CODE_REG. |
| 1951 __ LoadImmediate(IP, kZapCodeReg); | 1903 __ LoadImmediate(IP, kZapCodeReg); |
| 1952 __ Push(IP); | 1904 __ Push(IP); |
| 1953 | 1905 |
| 1954 // Load the deopt pc into LR. | 1906 // Load the deopt pc into LR. |
| 1955 __ LoadFromOffset(kWord, LR, THR, Thread::resume_pc_offset()); | 1907 __ LoadFromOffset(kWord, LR, THR, Thread::resume_pc_offset()); |
| 1956 GenerateDeoptimizationSequence(assembler, kEagerDeopt); | 1908 GenerateDeoptimizationSequence(assembler, kEagerDeopt); |
| 1957 | 1909 |
| 1958 // After we have deoptimized, jump to the correct frame. | 1910 // After we have deoptimized, jump to the correct frame. |
| 1959 __ EnterStubFrame(); | 1911 __ EnterStubFrame(); |
| 1960 __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0); | 1912 __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0); |
| 1961 __ LeaveStubFrame(); | 1913 __ LeaveStubFrame(); |
| 1962 __ bkpt(0); | 1914 __ bkpt(0); |
| 1963 } | 1915 } |
| 1964 | 1916 |
| 1965 | |
| 1966 // Calls to the runtime to optimize the given function. | 1917 // Calls to the runtime to optimize the given function. |
| 1967 // R8: function to be reoptimized. | 1918 // R8: function to be reoptimized. |
| 1968 // R4: argument descriptor (preserved). | 1919 // R4: argument descriptor (preserved). |
| 1969 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { | 1920 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { |
| 1970 __ EnterStubFrame(); | 1921 __ EnterStubFrame(); |
| 1971 __ Push(R4); | 1922 __ Push(R4); |
| 1972 __ LoadImmediate(IP, 0); | 1923 __ LoadImmediate(IP, 0); |
| 1973 __ Push(IP); // Setup space on stack for return value. | 1924 __ Push(IP); // Setup space on stack for return value. |
| 1974 __ Push(R8); | 1925 __ Push(R8); |
| 1975 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); | 1926 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); |
| 1976 __ Pop(R0); // Discard argument. | 1927 __ Pop(R0); // Discard argument. |
| 1977 __ Pop(R0); // Get Function object | 1928 __ Pop(R0); // Get Function object |
| 1978 __ Pop(R4); // Restore argument descriptor. | 1929 __ Pop(R4); // Restore argument descriptor. |
| 1979 __ LeaveStubFrame(); | 1930 __ LeaveStubFrame(); |
| 1980 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 1931 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
| 1981 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); | 1932 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); |
| 1982 __ bx(R1); | 1933 __ bx(R1); |
| 1983 __ bkpt(0); | 1934 __ bkpt(0); |
| 1984 } | 1935 } |
| 1985 | 1936 |
| 1986 | |
| 1987 // Does identical check (object references are equal or not equal) with special | 1937 // Does identical check (object references are equal or not equal) with special |
| 1988 // checks for boxed numbers. | 1938 // checks for boxed numbers. |
| 1989 // LR: return address. | 1939 // LR: return address. |
| 1990 // Return Zero condition flag set if equal. | 1940 // Return Zero condition flag set if equal. |
| 1991 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint | 1941 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint |
| 1992 // cannot contain a value that fits in Mint or Smi. | 1942 // cannot contain a value that fits in Mint or Smi. |
| 1993 static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler, | 1943 static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler, |
| 1994 const Register left, | 1944 const Register left, |
| 1995 const Register right, | 1945 const Register right, |
| 1996 const Register temp) { | 1946 const Register temp) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2043 // Result in R0, 0 means equal. | 1993 // Result in R0, 0 means equal. |
| 2044 __ LeaveStubFrame(); | 1994 __ LeaveStubFrame(); |
| 2045 __ cmp(R0, Operand(0)); | 1995 __ cmp(R0, Operand(0)); |
| 2046 __ b(&done); | 1996 __ b(&done); |
| 2047 | 1997 |
| 2048 __ Bind(&reference_compare); | 1998 __ Bind(&reference_compare); |
| 2049 __ cmp(left, Operand(right)); | 1999 __ cmp(left, Operand(right)); |
| 2050 __ Bind(&done); | 2000 __ Bind(&done); |
| 2051 } | 2001 } |
| 2052 | 2002 |
| 2053 | |
| 2054 // Called only from unoptimized code. All relevant registers have been saved. | 2003 // Called only from unoptimized code. All relevant registers have been saved. |
| 2055 // LR: return address. | 2004 // LR: return address. |
| 2056 // SP + 4: left operand. | 2005 // SP + 4: left operand. |
| 2057 // SP + 0: right operand. | 2006 // SP + 0: right operand. |
| 2058 // Return Zero condition flag set if equal. | 2007 // Return Zero condition flag set if equal. |
| 2059 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 2008 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
| 2060 Assembler* assembler) { | 2009 Assembler* assembler) { |
| 2061 // Check single stepping. | 2010 // Check single stepping. |
| 2062 Label stepping, done_stepping; | 2011 Label stepping, done_stepping; |
| 2063 if (FLAG_support_debugger) { | 2012 if (FLAG_support_debugger) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2079 if (FLAG_support_debugger) { | 2028 if (FLAG_support_debugger) { |
| 2080 __ Bind(&stepping); | 2029 __ Bind(&stepping); |
| 2081 __ EnterStubFrame(); | 2030 __ EnterStubFrame(); |
| 2082 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 2031 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 2083 __ RestoreCodePointer(); | 2032 __ RestoreCodePointer(); |
| 2084 __ LeaveStubFrame(); | 2033 __ LeaveStubFrame(); |
| 2085 __ b(&done_stepping); | 2034 __ b(&done_stepping); |
| 2086 } | 2035 } |
| 2087 } | 2036 } |
| 2088 | 2037 |
| 2089 | |
| 2090 // Called from optimized code only. | 2038 // Called from optimized code only. |
| 2091 // LR: return address. | 2039 // LR: return address. |
| 2092 // SP + 4: left operand. | 2040 // SP + 4: left operand. |
| 2093 // SP + 0: right operand. | 2041 // SP + 0: right operand. |
| 2094 // Return Zero condition flag set if equal. | 2042 // Return Zero condition flag set if equal. |
| 2095 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( | 2043 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( |
| 2096 Assembler* assembler) { | 2044 Assembler* assembler) { |
| 2097 const Register temp = R2; | 2045 const Register temp = R2; |
| 2098 const Register left = R1; | 2046 const Register left = R1; |
| 2099 const Register right = R0; | 2047 const Register right = R0; |
| 2100 __ ldr(left, Address(SP, 1 * kWordSize)); | 2048 __ ldr(left, Address(SP, 1 * kWordSize)); |
| 2101 __ ldr(right, Address(SP, 0 * kWordSize)); | 2049 __ ldr(right, Address(SP, 0 * kWordSize)); |
| 2102 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2050 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2103 __ Ret(); | 2051 __ Ret(); |
| 2104 } | 2052 } |
| 2105 | 2053 |
| 2106 | |
| 2107 // Called from megamorphic calls. | 2054 // Called from megamorphic calls. |
| 2108 // R0: receiver | 2055 // R0: receiver |
| 2109 // R9: MegamorphicCache (preserved) | 2056 // R9: MegamorphicCache (preserved) |
| 2110 // Passed to target: | 2057 // Passed to target: |
| 2111 // CODE_REG: target Code | 2058 // CODE_REG: target Code |
| 2112 // R4: arguments descriptor | 2059 // R4: arguments descriptor |
| 2113 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { | 2060 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { |
| 2114 __ LoadTaggedClassIdMayBeSmi(R0, R0); | 2061 __ LoadTaggedClassIdMayBeSmi(R0, R0); |
| 2115 // R0: receiver cid as Smi. | 2062 // R0: receiver cid as Smi. |
| 2116 __ ldr(R2, FieldAddress(R9, MegamorphicCache::buckets_offset())); | 2063 __ ldr(R2, FieldAddress(R9, MegamorphicCache::buckets_offset())); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2151 __ Bind(&probe_failed); | 2098 __ Bind(&probe_failed); |
| 2152 ASSERT(kIllegalCid == 0); | 2099 ASSERT(kIllegalCid == 0); |
| 2153 __ tst(R6, Operand(R6)); | 2100 __ tst(R6, Operand(R6)); |
| 2154 __ b(&load_target, EQ); // branch if miss. | 2101 __ b(&load_target, EQ); // branch if miss. |
| 2155 | 2102 |
| 2156 // Try next entry in the table. | 2103 // Try next entry in the table. |
| 2157 __ AddImmediate(R3, Smi::RawValue(1)); | 2104 __ AddImmediate(R3, Smi::RawValue(1)); |
| 2158 __ b(&loop); | 2105 __ b(&loop); |
| 2159 } | 2106 } |
| 2160 | 2107 |
| 2161 | |
| 2162 // Called from switchable IC calls. | 2108 // Called from switchable IC calls. |
| 2163 // R0: receiver | 2109 // R0: receiver |
| 2164 // R9: ICData (preserved) | 2110 // R9: ICData (preserved) |
| 2165 // Passed to target: | 2111 // Passed to target: |
| 2166 // CODE_REG: target Code object | 2112 // CODE_REG: target Code object |
| 2167 // R4: arguments descriptor | 2113 // R4: arguments descriptor |
| 2168 void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) { | 2114 void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) { |
| 2169 Label loop, found, miss; | 2115 Label loop, found, miss; |
| 2170 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); | 2116 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); |
| 2171 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); | 2117 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2192 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 2138 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
| 2193 __ bx(R1); | 2139 __ bx(R1); |
| 2194 | 2140 |
| 2195 __ Bind(&miss); | 2141 __ Bind(&miss); |
| 2196 __ LoadIsolate(R2); | 2142 __ LoadIsolate(R2); |
| 2197 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); | 2143 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); |
| 2198 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); | 2144 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); |
| 2199 __ bx(R1); | 2145 __ bx(R1); |
| 2200 } | 2146 } |
| 2201 | 2147 |
| 2202 | |
| 2203 void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) { | 2148 void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) { |
| 2204 Label loop, found, miss; | 2149 Label loop, found, miss; |
| 2205 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); | 2150 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); |
| 2206 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); | 2151 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); |
| 2207 __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag); | 2152 __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag); |
| 2208 // R8: first IC entry | 2153 // R8: first IC entry |
| 2209 __ LoadTaggedClassIdMayBeSmi(R1, R0); | 2154 __ LoadTaggedClassIdMayBeSmi(R1, R0); |
| 2210 // R1: receiver cid as Smi | 2155 // R1: receiver cid as Smi |
| 2211 | 2156 |
| 2212 __ Bind(&loop); | 2157 __ Bind(&loop); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2227 __ ldr(CODE_REG, Address(R8, code_offset)); | 2172 __ ldr(CODE_REG, Address(R8, code_offset)); |
| 2228 __ bx(R1); | 2173 __ bx(R1); |
| 2229 | 2174 |
| 2230 __ Bind(&miss); | 2175 __ Bind(&miss); |
| 2231 __ LoadIsolate(R2); | 2176 __ LoadIsolate(R2); |
| 2232 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); | 2177 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); |
| 2233 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); | 2178 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); |
| 2234 __ bx(R1); | 2179 __ bx(R1); |
| 2235 } | 2180 } |
| 2236 | 2181 |
| 2237 | |
| 2238 // Called from switchable IC calls. | 2182 // Called from switchable IC calls. |
| 2239 // R0: receiver | 2183 // R0: receiver |
| 2240 // R9: UnlinkedCall | 2184 // R9: UnlinkedCall |
| 2241 void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) { | 2185 void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) { |
| 2242 __ EnterStubFrame(); | 2186 __ EnterStubFrame(); |
| 2243 __ Push(R0); // Preserve receiver. | 2187 __ Push(R0); // Preserve receiver. |
| 2244 | 2188 |
| 2245 __ LoadImmediate(IP, 0); | 2189 __ LoadImmediate(IP, 0); |
| 2246 __ Push(IP); // Result slot | 2190 __ Push(IP); // Result slot |
| 2247 __ Push(R0); // Arg0: Receiver | 2191 __ Push(R0); // Arg0: Receiver |
| 2248 __ Push(R9); // Arg1: UnlinkedCall | 2192 __ Push(R9); // Arg1: UnlinkedCall |
| 2249 __ CallRuntime(kUnlinkedCallRuntimeEntry, 2); | 2193 __ CallRuntime(kUnlinkedCallRuntimeEntry, 2); |
| 2250 __ Drop(2); | 2194 __ Drop(2); |
| 2251 __ Pop(R9); // result = IC | 2195 __ Pop(R9); // result = IC |
| 2252 | 2196 |
| 2253 __ Pop(R0); // Restore receiver. | 2197 __ Pop(R0); // Restore receiver. |
| 2254 __ LeaveStubFrame(); | 2198 __ LeaveStubFrame(); |
| 2255 | 2199 |
| 2256 __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); | 2200 __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); |
| 2257 __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); | 2201 __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); |
| 2258 __ bx(R1); | 2202 __ bx(R1); |
| 2259 } | 2203 } |
| 2260 | 2204 |
| 2261 | |
| 2262 // Called from switchable IC calls. | 2205 // Called from switchable IC calls. |
| 2263 // R0: receiver | 2206 // R0: receiver |
| 2264 // R9: SingleTargetCache | 2207 // R9: SingleTargetCache |
| 2265 // Passed to target: | 2208 // Passed to target: |
| 2266 // CODE_REG: target Code object | 2209 // CODE_REG: target Code object |
| 2267 void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) { | 2210 void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) { |
| 2268 Label miss; | 2211 Label miss; |
| 2269 __ LoadClassIdMayBeSmi(R1, R0); | 2212 __ LoadClassIdMayBeSmi(R1, R0); |
| 2270 __ ldrh(R2, FieldAddress(R9, SingleTargetCache::lower_limit_offset())); | 2213 __ ldrh(R2, FieldAddress(R9, SingleTargetCache::lower_limit_offset())); |
| 2271 __ ldrh(R3, FieldAddress(R9, SingleTargetCache::upper_limit_offset())); | 2214 __ ldrh(R3, FieldAddress(R9, SingleTargetCache::upper_limit_offset())); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2291 __ Pop(R9); // result = IC | 2234 __ Pop(R9); // result = IC |
| 2292 | 2235 |
| 2293 __ Pop(R0); // Restore receiver. | 2236 __ Pop(R0); // Restore receiver. |
| 2294 __ LeaveStubFrame(); | 2237 __ LeaveStubFrame(); |
| 2295 | 2238 |
| 2296 __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); | 2239 __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); |
| 2297 __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); | 2240 __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); |
| 2298 __ bx(R1); | 2241 __ bx(R1); |
| 2299 } | 2242 } |
| 2300 | 2243 |
| 2301 | |
| 2302 // Called from the monomorphic checked entry. | 2244 // Called from the monomorphic checked entry. |
| 2303 // R0: receiver | 2245 // R0: receiver |
| 2304 void StubCode::GenerateMonomorphicMissStub(Assembler* assembler) { | 2246 void StubCode::GenerateMonomorphicMissStub(Assembler* assembler) { |
| 2305 __ ldr(CODE_REG, Address(THR, Thread::monomorphic_miss_stub_offset())); | 2247 __ ldr(CODE_REG, Address(THR, Thread::monomorphic_miss_stub_offset())); |
| 2306 __ EnterStubFrame(); | 2248 __ EnterStubFrame(); |
| 2307 __ Push(R0); // Preserve receiver. | 2249 __ Push(R0); // Preserve receiver. |
| 2308 | 2250 |
| 2309 __ LoadImmediate(IP, 0); | 2251 __ LoadImmediate(IP, 0); |
| 2310 __ Push(IP); // Result slot | 2252 __ Push(IP); // Result slot |
| 2311 __ Push(R0); // Arg0: Receiver | 2253 __ Push(R0); // Arg0: Receiver |
| 2312 __ CallRuntime(kMonomorphicMissRuntimeEntry, 1); | 2254 __ CallRuntime(kMonomorphicMissRuntimeEntry, 1); |
| 2313 __ Drop(1); | 2255 __ Drop(1); |
| 2314 __ Pop(R9); // result = IC | 2256 __ Pop(R9); // result = IC |
| 2315 | 2257 |
| 2316 __ Pop(R0); // Restore receiver. | 2258 __ Pop(R0); // Restore receiver. |
| 2317 __ LeaveStubFrame(); | 2259 __ LeaveStubFrame(); |
| 2318 | 2260 |
| 2319 __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); | 2261 __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); |
| 2320 __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); | 2262 __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); |
| 2321 __ bx(R1); | 2263 __ bx(R1); |
| 2322 } | 2264 } |
| 2323 | 2265 |
| 2324 | |
| 2325 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { | 2266 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { |
| 2326 __ bkpt(0); | 2267 __ bkpt(0); |
| 2327 } | 2268 } |
| 2328 | 2269 |
| 2329 | |
| 2330 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { | 2270 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { |
| 2331 __ bkpt(0); | 2271 __ bkpt(0); |
| 2332 } | 2272 } |
| 2333 | 2273 |
| 2334 } // namespace dart | 2274 } // namespace dart |
| 2335 | 2275 |
| 2336 #endif // defined TARGET_ARCH_ARM | 2276 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |