| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ | 28 #ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ |
| 29 #define V8_ARM_MACRO_ASSEMBLER_ARM_H_ | 29 #define V8_ARM_MACRO_ASSEMBLER_ARM_H_ |
| 30 | 30 |
| 31 #include "assembler.h" | 31 #include "assembler.h" |
| 32 | 32 |
| 33 namespace v8 { | 33 namespace v8 { |
| 34 namespace internal { | 34 namespace internal { |
| 35 | 35 |
| 36 // Forward declaration. |
| 37 class PostCallGenerator; |
| 38 |
| 36 // ---------------------------------------------------------------------------- | 39 // ---------------------------------------------------------------------------- |
| 37 // Static helper functions | 40 // Static helper functions |
| 38 | 41 |
| 39 // Generate a MemOperand for loading a field from an object. | 42 // Generate a MemOperand for loading a field from an object. |
| 40 static inline MemOperand FieldMemOperand(Register object, int offset) { | 43 static inline MemOperand FieldMemOperand(Register object, int offset) { |
| 41 return MemOperand(object, offset - kHeapObjectTag); | 44 return MemOperand(object, offset - kHeapObjectTag); |
| 42 } | 45 } |
| 43 | 46 |
| 44 | 47 |
| 48 static inline Operand SmiUntagOperand(Register object) { |
| 49 return Operand(object, ASR, kSmiTagSize); |
| 50 } |
| 51 |
| 52 |
| 53 |
| 45 // Give alias names to registers | 54 // Give alias names to registers |
| 46 const Register cp = { 8 }; // JavaScript context pointer | 55 const Register cp = { 8 }; // JavaScript context pointer |
| 47 const Register roots = { 10 }; // Roots array pointer. | 56 const Register roots = { 10 }; // Roots array pointer. |
| 48 | 57 |
| 49 enum InvokeJSFlags { | 58 enum InvokeJSFlags { |
| 50 CALL_JS, | 59 CALL_JS, |
| 51 JUMP_JS | 60 JUMP_JS |
| 52 }; | 61 }; |
| 53 | 62 |
| 54 | 63 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 // Store an object to the root table. | 138 // Store an object to the root table. |
| 130 void StoreRoot(Register source, | 139 void StoreRoot(Register source, |
| 131 Heap::RootListIndex index, | 140 Heap::RootListIndex index, |
| 132 Condition cond = al); | 141 Condition cond = al); |
| 133 | 142 |
| 134 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER | 143 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 135 // Check if object is in new space. | 144 // Check if object is in new space. |
| 136 // scratch can be object itself, but it will be clobbered. | 145 // scratch can be object itself, but it will be clobbered. |
| 137 void InNewSpace(Register object, | 146 void InNewSpace(Register object, |
| 138 Register scratch, | 147 Register scratch, |
| 139 Condition cc, // eq for new space, ne otherwise | 148 Condition cond, // eq for new space, ne otherwise |
| 140 Label* branch); | 149 Label* branch); |
| 141 | 150 |
| 142 | 151 |
| 143 // For the page containing |object| mark the region covering [address] | 152 // For the page containing |object| mark the region covering [address] |
| 144 // dirty. The object address must be in the first 8K of an allocated page. | 153 // dirty. The object address must be in the first 8K of an allocated page. |
| 145 void RecordWriteHelper(Register object, | 154 void RecordWriteHelper(Register object, |
| 146 Register address, | 155 Register address, |
| 147 Register scratch); | 156 Register scratch); |
| 148 | 157 |
| 149 // For the page containing |object| mark the region covering | 158 // For the page containing |object| mark the region covering |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 } else { | 232 } else { |
| 224 str(src1, MemOperand(sp, 4, NegPreIndex), cond); | 233 str(src1, MemOperand(sp, 4, NegPreIndex), cond); |
| 225 Push(src2, src3, src4, cond); | 234 Push(src2, src3, src4, cond); |
| 226 } | 235 } |
| 227 } | 236 } |
| 228 | 237 |
| 229 // Push and pop the registers that can hold pointers, as defined by the | 238 // Push and pop the registers that can hold pointers, as defined by the |
| 230 // RegList constant kSafepointSavedRegisters. | 239 // RegList constant kSafepointSavedRegisters. |
| 231 void PushSafepointRegisters(); | 240 void PushSafepointRegisters(); |
| 232 void PopSafepointRegisters(); | 241 void PopSafepointRegisters(); |
| 242 void PushSafepointRegistersAndDoubles(); |
| 243 void PopSafepointRegistersAndDoubles(); |
| 244 void StoreToSafepointRegisterSlot(Register reg); |
| 245 void StoreToSafepointRegistersAndDoublesSlot(Register reg); |
| 246 void LoadFromSafepointRegisterSlot(Register reg); |
| 233 static int SafepointRegisterStackIndex(int reg_code); | 247 static int SafepointRegisterStackIndex(int reg_code); |
| 248 static MemOperand SafepointRegisterSlot(Register reg); |
| 249 static MemOperand SafepointRegistersAndDoublesSlot(Register reg); |
| 234 | 250 |
| 235 // Load two consecutive registers with two consecutive memory locations. | 251 // Load two consecutive registers with two consecutive memory locations. |
| 236 void Ldrd(Register dst1, | 252 void Ldrd(Register dst1, |
| 237 Register dst2, | 253 Register dst2, |
| 238 const MemOperand& src, | 254 const MemOperand& src, |
| 239 Condition cond = al); | 255 Condition cond = al); |
| 240 | 256 |
| 241 // Store two consecutive registers to two consecutive memory locations. | 257 // Store two consecutive registers to two consecutive memory locations. |
| 242 void Strd(Register src1, | 258 void Strd(Register src1, |
| 243 Register src2, | 259 Register src2, |
| 244 const MemOperand& dst, | 260 const MemOperand& dst, |
| 245 Condition cond = al); | 261 Condition cond = al); |
| 246 | 262 |
| 263 // Clear specified FPSCR bits. |
| 264 void ClearFPSCRBits(const uint32_t bits_to_clear, |
| 265 const Register scratch, |
| 266 const Condition cond = al); |
| 267 |
| 268 // Compare double values and move the result to the normal condition flags. |
| 269 void VFPCompareAndSetFlags(const DwVfpRegister src1, |
| 270 const DwVfpRegister src2, |
| 271 const Condition cond = al); |
| 272 void VFPCompareAndSetFlags(const DwVfpRegister src1, |
| 273 const double src2, |
| 274 const Condition cond = al); |
| 275 |
| 276 // Compare double values and then load the fpscr flags to a register. |
| 277 void VFPCompareAndLoadFlags(const DwVfpRegister src1, |
| 278 const DwVfpRegister src2, |
| 279 const Register fpscr_flags, |
| 280 const Condition cond = al); |
| 281 void VFPCompareAndLoadFlags(const DwVfpRegister src1, |
| 282 const double src2, |
| 283 const Register fpscr_flags, |
| 284 const Condition cond = al); |
| 285 |
| 286 |
| 247 // --------------------------------------------------------------------------- | 287 // --------------------------------------------------------------------------- |
| 248 // Activation frames | 288 // Activation frames |
| 249 | 289 |
| 250 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); } | 290 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); } |
| 251 void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); } | 291 void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); } |
| 252 | 292 |
| 253 void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); } | 293 void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); } |
| 254 void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); } | 294 void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); } |
| 255 | 295 |
| 256 // Enter exit frame. | 296 // Enter exit frame. |
| 257 // Expects the number of arguments in register r0 and | 297 // stack_space - extra stack space, used for alignment before call to C. |
| 258 // the builtin function to call in register r1. Exits with argc in | 298 void EnterExitFrame(bool save_doubles, int stack_space = 0); |
| 259 // r4, argv in r6, and and the builtin function to call in r5. | |
| 260 void EnterExitFrame(bool save_doubles); | |
| 261 | 299 |
| 262 // Leave the current exit frame. Expects the return value in r0. | 300 // Leave the current exit frame. Expects the return value in r0. |
| 263 void LeaveExitFrame(bool save_doubles); | 301 // Expect the number of values, pushed prior to the exit frame, to |
| 302 // remove in a register (or no_reg, if there is nothing to remove). |
| 303 void LeaveExitFrame(bool save_doubles, Register argument_count); |
| 264 | 304 |
| 265 // Get the actual activation frame alignment for target environment. | 305 // Get the actual activation frame alignment for target environment. |
| 266 static int ActivationFrameAlignment(); | 306 static int ActivationFrameAlignment(); |
| 267 | 307 |
| 268 void LoadContext(Register dst, int context_chain_length); | 308 void LoadContext(Register dst, int context_chain_length); |
| 269 | 309 |
| 270 void LoadGlobalFunction(int index, Register function); | 310 void LoadGlobalFunction(int index, Register function); |
| 271 | 311 |
| 272 // Load the initial map from the global function. The registers | 312 // Load the initial map from the global function. The registers |
| 273 // function and map can be the same, function is then overwritten. | 313 // function and map can be the same, function is then overwritten. |
| 274 void LoadGlobalFunctionInitialMap(Register function, | 314 void LoadGlobalFunctionInitialMap(Register function, |
| 275 Register map, | 315 Register map, |
| 276 Register scratch); | 316 Register scratch); |
| 277 | 317 |
| 278 // --------------------------------------------------------------------------- | 318 // --------------------------------------------------------------------------- |
| 279 // JavaScript invokes | 319 // JavaScript invokes |
| 280 | 320 |
| 281 // Invoke the JavaScript function code by either calling or jumping. | 321 // Invoke the JavaScript function code by either calling or jumping. |
| 282 void InvokeCode(Register code, | 322 void InvokeCode(Register code, |
| 283 const ParameterCount& expected, | 323 const ParameterCount& expected, |
| 284 const ParameterCount& actual, | 324 const ParameterCount& actual, |
| 285 InvokeFlag flag); | 325 InvokeFlag flag, |
| 326 PostCallGenerator* post_call_generator = NULL); |
| 286 | 327 |
| 287 void InvokeCode(Handle<Code> code, | 328 void InvokeCode(Handle<Code> code, |
| 288 const ParameterCount& expected, | 329 const ParameterCount& expected, |
| 289 const ParameterCount& actual, | 330 const ParameterCount& actual, |
| 290 RelocInfo::Mode rmode, | 331 RelocInfo::Mode rmode, |
| 291 InvokeFlag flag); | 332 InvokeFlag flag); |
| 292 | 333 |
| 293 // Invoke the JavaScript function in the given register. Changes the | 334 // Invoke the JavaScript function in the given register. Changes the |
| 294 // current context to the context in the function before invoking. | 335 // current context to the context in the function before invoking. |
| 295 void InvokeFunction(Register function, | 336 void InvokeFunction(Register function, |
| 296 const ParameterCount& actual, | 337 const ParameterCount& actual, |
| 297 InvokeFlag flag); | 338 InvokeFlag flag, |
| 339 PostCallGenerator* post_call_generator = NULL); |
| 298 | 340 |
| 299 void InvokeFunction(JSFunction* function, | 341 void InvokeFunction(JSFunction* function, |
| 300 const ParameterCount& actual, | 342 const ParameterCount& actual, |
| 301 InvokeFlag flag); | 343 InvokeFlag flag); |
| 302 | 344 |
| 303 void IsObjectJSObjectType(Register heap_object, | 345 void IsObjectJSObjectType(Register heap_object, |
| 304 Register map, | 346 Register map, |
| 305 Register scratch, | 347 Register scratch, |
| 306 Label* fail); | 348 Label* fail); |
| 307 | 349 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 325 | 367 |
| 326 // Push a new try handler and link into try handler chain. | 368 // Push a new try handler and link into try handler chain. |
| 327 // The return address must be passed in register lr. | 369 // The return address must be passed in register lr. |
| 328 // On exit, r0 contains TOS (code slot). | 370 // On exit, r0 contains TOS (code slot). |
| 329 void PushTryHandler(CodeLocation try_location, HandlerType type); | 371 void PushTryHandler(CodeLocation try_location, HandlerType type); |
| 330 | 372 |
| 331 // Unlink the stack handler on top of the stack from the try handler chain. | 373 // Unlink the stack handler on top of the stack from the try handler chain. |
| 332 // Must preserve the result register. | 374 // Must preserve the result register. |
| 333 void PopTryHandler(); | 375 void PopTryHandler(); |
| 334 | 376 |
| 377 // Passes thrown value (in r0) to the handler of top of the try handler chain. |
| 378 void Throw(Register value); |
| 379 |
| 380 // Propagates an uncatchable exception to the top of the current JS stack's |
| 381 // handler chain. |
| 382 void ThrowUncatchable(UncatchableExceptionType type, Register value); |
| 383 |
| 335 // --------------------------------------------------------------------------- | 384 // --------------------------------------------------------------------------- |
| 336 // Inline caching support | 385 // Inline caching support |
| 337 | 386 |
| 338 // Generate code for checking access rights - used for security checks | 387 // Generate code for checking access rights - used for security checks |
| 339 // on access to global objects across environments. The holder register | 388 // on access to global objects across environments. The holder register |
| 340 // is left untouched, whereas both scratch registers are clobbered. | 389 // is left untouched, whereas both scratch registers are clobbered. |
| 341 void CheckAccessGlobalProxy(Register holder_reg, | 390 void CheckAccessGlobalProxy(Register holder_reg, |
| 342 Register scratch, | 391 Register scratch, |
| 343 Label* miss); | 392 Label* miss); |
| 344 | 393 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 373 : -1; | 422 : -1; |
| 374 ASSERT((type == -1) || | 423 ASSERT((type == -1) || |
| 375 ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER))); | 424 ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER))); |
| 376 return type; | 425 return type; |
| 377 } | 426 } |
| 378 | 427 |
| 379 | 428 |
| 380 // --------------------------------------------------------------------------- | 429 // --------------------------------------------------------------------------- |
| 381 // Allocation support | 430 // Allocation support |
| 382 | 431 |
| 383 // Allocate an object in new space. The object_size is specified in words (not | 432 // Allocate an object in new space. The object_size is specified |
| 384 // bytes). If the new space is exhausted control continues at the gc_required | 433 // either in bytes or in words if the allocation flag SIZE_IN_WORDS |
| 385 // label. The allocated object is returned in result. If the flag | 434 // is passed. If the new space is exhausted control continues at the |
| 386 // tag_allocated_object is true the result is tagged as as a heap object. All | 435 // gc_required label. The allocated object is returned in result. If |
| 387 // registers are clobbered also when control continues at the gc_required | 436 // the flag tag_allocated_object is true the result is tagged as as |
| 388 // label. | 437 // a heap object. All registers are clobbered also when control |
| 438 // continues at the gc_required label. |
| 389 void AllocateInNewSpace(int object_size, | 439 void AllocateInNewSpace(int object_size, |
| 390 Register result, | 440 Register result, |
| 391 Register scratch1, | 441 Register scratch1, |
| 392 Register scratch2, | 442 Register scratch2, |
| 393 Label* gc_required, | 443 Label* gc_required, |
| 394 AllocationFlags flags); | 444 AllocationFlags flags); |
| 395 void AllocateInNewSpace(Register object_size, | 445 void AllocateInNewSpace(Register object_size, |
| 396 Register result, | 446 Register result, |
| 397 Register scratch1, | 447 Register scratch1, |
| 398 Register scratch2, | 448 Register scratch2, |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 Condition IsObjectStringType(Register obj, | 555 Condition IsObjectStringType(Register obj, |
| 506 Register type) { | 556 Register type) { |
| 507 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset)); | 557 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset)); |
| 508 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset)); | 558 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset)); |
| 509 tst(type, Operand(kIsNotStringMask)); | 559 tst(type, Operand(kIsNotStringMask)); |
| 510 ASSERT_EQ(0, kStringTag); | 560 ASSERT_EQ(0, kStringTag); |
| 511 return eq; | 561 return eq; |
| 512 } | 562 } |
| 513 | 563 |
| 514 | 564 |
| 515 inline void BranchOnSmi(Register value, Label* smi_label) { | |
| 516 tst(value, Operand(kSmiTagMask)); | |
| 517 b(eq, smi_label); | |
| 518 } | |
| 519 | |
| 520 inline void BranchOnNotSmi(Register value, Label* not_smi_label) { | |
| 521 tst(value, Operand(kSmiTagMask)); | |
| 522 b(ne, not_smi_label); | |
| 523 } | |
| 524 | |
| 525 // Generates code for reporting that an illegal operation has | 565 // Generates code for reporting that an illegal operation has |
| 526 // occurred. | 566 // occurred. |
| 527 void IllegalOperation(int num_arguments); | 567 void IllegalOperation(int num_arguments); |
| 528 | 568 |
| 529 // Picks out an array index from the hash field. | 569 // Picks out an array index from the hash field. |
| 530 // Register use: | 570 // Register use: |
| 531 // hash - holds the index's hash. Clobbered. | 571 // hash - holds the index's hash. Clobbered. |
| 532 // index - holds the overwritten index on exit. | 572 // index - holds the overwritten index on exit. |
| 533 void IndexFromHash(Register hash, Register index); | 573 void IndexFromHash(Register hash, Register index); |
| 534 | 574 |
| 535 // Get the number of least significant bits from a register | 575 // Get the number of least significant bits from a register |
| 536 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); | 576 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); |
| 577 void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits); |
| 537 | 578 |
| 538 // Uses VFP instructions to Convert a Smi to a double. | 579 // Uses VFP instructions to Convert a Smi to a double. |
| 539 void IntegerToDoubleConversionWithVFP3(Register inReg, | 580 void IntegerToDoubleConversionWithVFP3(Register inReg, |
| 540 Register outHighReg, | 581 Register outHighReg, |
| 541 Register outLowReg); | 582 Register outLowReg); |
| 542 | 583 |
| 543 // Load the value of a number object into a VFP double register. If the object | 584 // Load the value of a number object into a VFP double register. If the object |
| 544 // is not a number a jump to the label not_number is performed and the VFP | 585 // is not a number a jump to the label not_number is performed and the VFP |
| 545 // double register is unchanged. | 586 // double register is unchanged. |
| 546 void ObjectToDoubleVFPRegister( | 587 void ObjectToDoubleVFPRegister( |
| 547 Register object, | 588 Register object, |
| 548 DwVfpRegister value, | 589 DwVfpRegister value, |
| 549 Register scratch1, | 590 Register scratch1, |
| 550 Register scratch2, | 591 Register scratch2, |
| 551 Register heap_number_map, | 592 Register heap_number_map, |
| 552 SwVfpRegister scratch3, | 593 SwVfpRegister scratch3, |
| 553 Label* not_number, | 594 Label* not_number, |
| 554 ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS); | 595 ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS); |
| 555 | 596 |
| 556 // Load the value of a smi object into a VFP double register. The register | 597 // Load the value of a smi object into a VFP double register. The register |
| 557 // scratch1 can be the same register as smi in which case smi will hold the | 598 // scratch1 can be the same register as smi in which case smi will hold the |
| 558 // untagged value afterwards. | 599 // untagged value afterwards. |
| 559 void SmiToDoubleVFPRegister(Register smi, | 600 void SmiToDoubleVFPRegister(Register smi, |
| 560 DwVfpRegister value, | 601 DwVfpRegister value, |
| 561 Register scratch1, | 602 Register scratch1, |
| 562 SwVfpRegister scratch2); | 603 SwVfpRegister scratch2); |
| 563 | 604 |
| 564 // Convert the HeapNumber pointed to by source to a 32bits signed integer | 605 // Convert the HeapNumber pointed to by source to a 32bits signed integer |
| 565 // dest. If the HeapNumber does not fit into a 32bits signed integer branch | 606 // dest. If the HeapNumber does not fit into a 32bits signed integer branch |
| 566 // to not_int32 label. | 607 // to not_int32 label. If VFP3 is available double_scratch is used but not |
| 608 // scratch2. |
| 567 void ConvertToInt32(Register source, | 609 void ConvertToInt32(Register source, |
| 568 Register dest, | 610 Register dest, |
| 569 Register scratch, | 611 Register scratch, |
| 570 Register scratch2, | 612 Register scratch2, |
| 613 DwVfpRegister double_scratch, |
| 571 Label *not_int32); | 614 Label *not_int32); |
| 572 | 615 |
| 573 // Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz | 616 // Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz |
| 574 // instruction. On pre-ARM5 hardware this routine gives the wrong answer | 617 // instruction. On pre-ARM5 hardware this routine gives the wrong answer |
| 575 // for 0 (31 instead of 32). Source and scratch can be the same in which case | 618 // for 0 (31 instead of 32). Source and scratch can be the same in which case |
| 576 // the source is clobbered. Source and zeros can also be the same in which | 619 // the source is clobbered. Source and zeros can also be the same in which |
| 577 // case scratch should be a different register. | 620 // case scratch should be a different register. |
| 578 void CountLeadingZeros(Register zeros, | 621 void CountLeadingZeros(Register zeros, |
| 579 Register source, | 622 Register source, |
| 580 Register scratch); | 623 Register scratch); |
| 581 | 624 |
| 582 // --------------------------------------------------------------------------- | 625 // --------------------------------------------------------------------------- |
| 583 // Runtime calls | 626 // Runtime calls |
| 584 | 627 |
| 585 // Call a code stub. | 628 // Call a code stub. |
| 586 void CallStub(CodeStub* stub, Condition cond = al); | 629 void CallStub(CodeStub* stub, Condition cond = al); |
| 587 | 630 |
| 588 // Call a code stub. | 631 // Call a code stub. |
| 589 void TailCallStub(CodeStub* stub, Condition cond = al); | 632 void TailCallStub(CodeStub* stub, Condition cond = al); |
| 590 | 633 |
| 634 // Tail call a code stub (jump) and return the code object called. Try to |
| 635 // generate the code if necessary. Do not perform a GC but instead return |
| 636 // a retry after GC failure. |
| 637 MUST_USE_RESULT MaybeObject* TryTailCallStub(CodeStub* stub, |
| 638 Condition cond = al); |
| 639 |
| 591 // Call a runtime routine. | 640 // Call a runtime routine. |
| 592 void CallRuntime(Runtime::Function* f, int num_arguments); | 641 void CallRuntime(Runtime::Function* f, int num_arguments); |
| 593 void CallRuntimeSaveDoubles(Runtime::FunctionId id); | 642 void CallRuntimeSaveDoubles(Runtime::FunctionId id); |
| 594 | 643 |
| 595 // Convenience function: Same as above, but takes the fid instead. | 644 // Convenience function: Same as above, but takes the fid instead. |
| 596 void CallRuntime(Runtime::FunctionId fid, int num_arguments); | 645 void CallRuntime(Runtime::FunctionId fid, int num_arguments); |
| 597 | 646 |
| 598 // Convenience function: call an external reference. | 647 // Convenience function: call an external reference. |
| 599 void CallExternalReference(const ExternalReference& ext, | 648 void CallExternalReference(const ExternalReference& ext, |
| 600 int num_arguments); | 649 int num_arguments); |
| 601 | 650 |
| 602 // Tail call of a runtime routine (jump). | 651 // Tail call of a runtime routine (jump). |
| 603 // Like JumpToExternalReference, but also takes care of passing the number | 652 // Like JumpToExternalReference, but also takes care of passing the number |
| 604 // of parameters. | 653 // of parameters. |
| 605 void TailCallExternalReference(const ExternalReference& ext, | 654 void TailCallExternalReference(const ExternalReference& ext, |
| 606 int num_arguments, | 655 int num_arguments, |
| 607 int result_size); | 656 int result_size); |
| 608 | 657 |
| 658 // Tail call of a runtime routine (jump). Try to generate the code if |
| 659 // necessary. Do not perform a GC but instead return a retry after GC |
| 660 // failure. |
| 661 MUST_USE_RESULT MaybeObject* TryTailCallExternalReference( |
| 662 const ExternalReference& ext, int num_arguments, int result_size); |
| 663 |
| 609 // Convenience function: tail call a runtime routine (jump). | 664 // Convenience function: tail call a runtime routine (jump). |
| 610 void TailCallRuntime(Runtime::FunctionId fid, | 665 void TailCallRuntime(Runtime::FunctionId fid, |
| 611 int num_arguments, | 666 int num_arguments, |
| 612 int result_size); | 667 int result_size); |
| 613 | 668 |
| 614 // Before calling a C-function from generated code, align arguments on stack. | 669 // Before calling a C-function from generated code, align arguments on stack. |
| 615 // After aligning the frame, non-register arguments must be stored in | 670 // After aligning the frame, non-register arguments must be stored in |
| 616 // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments | 671 // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments |
| 617 // are word sized. | 672 // are word sized. |
| 618 // Some compilers/platforms require the stack to be aligned when calling | 673 // Some compilers/platforms require the stack to be aligned when calling |
| 619 // C++ code. | 674 // C++ code. |
| 620 // Needs a scratch register to do some arithmetic. This register will be | 675 // Needs a scratch register to do some arithmetic. This register will be |
| 621 // trashed. | 676 // trashed. |
| 622 void PrepareCallCFunction(int num_arguments, Register scratch); | 677 void PrepareCallCFunction(int num_arguments, Register scratch); |
| 623 | 678 |
| 624 // Calls a C function and cleans up the space for arguments allocated | 679 // Calls a C function and cleans up the space for arguments allocated |
| 625 // by PrepareCallCFunction. The called function is not allowed to trigger a | 680 // by PrepareCallCFunction. The called function is not allowed to trigger a |
| 626 // garbage collection, since that might move the code and invalidate the | 681 // garbage collection, since that might move the code and invalidate the |
| 627 // return address (unless this is somehow accounted for by the called | 682 // return address (unless this is somehow accounted for by the called |
| 628 // function). | 683 // function). |
| 629 void CallCFunction(ExternalReference function, int num_arguments); | 684 void CallCFunction(ExternalReference function, int num_arguments); |
| 630 void CallCFunction(Register function, int num_arguments); | 685 void CallCFunction(Register function, int num_arguments); |
| 631 | 686 |
| 687 // Calls an API function. Allocates HandleScope, extracts returned value |
| 688 // from handle and propagates exceptions. Restores context. |
| 689 // stack_space - space to be unwound on exit (includes the call js |
| 690 // arguments space and the additional space allocated for the fast call). |
| 691 MaybeObject* TryCallApiFunctionAndReturn(ApiFunction* function, |
| 692 int stack_space); |
| 693 |
| 632 // Jump to a runtime routine. | 694 // Jump to a runtime routine. |
| 633 void JumpToExternalReference(const ExternalReference& builtin); | 695 void JumpToExternalReference(const ExternalReference& builtin); |
| 634 | 696 |
| 697 MaybeObject* TryJumpToExternalReference(const ExternalReference& ext); |
| 698 |
| 635 // Invoke specified builtin JavaScript function. Adds an entry to | 699 // Invoke specified builtin JavaScript function. Adds an entry to |
| 636 // the unresolved list if the name does not resolve. | 700 // the unresolved list if the name does not resolve. |
| 637 void InvokeBuiltin(Builtins::JavaScript id, InvokeJSFlags flags); | 701 void InvokeBuiltin(Builtins::JavaScript id, |
| 702 InvokeJSFlags flags, |
| 703 PostCallGenerator* post_call_generator = NULL); |
| 638 | 704 |
| 639 // Store the code object for the given builtin in the target register and | 705 // Store the code object for the given builtin in the target register and |
| 640 // setup the function in r1. | 706 // setup the function in r1. |
| 641 void GetBuiltinEntry(Register target, Builtins::JavaScript id); | 707 void GetBuiltinEntry(Register target, Builtins::JavaScript id); |
| 642 | 708 |
| 643 // Store the function for the given builtin in the target register. | 709 // Store the function for the given builtin in the target register. |
| 644 void GetBuiltinFunction(Register target, Builtins::JavaScript id); | 710 void GetBuiltinFunction(Register target, Builtins::JavaScript id); |
| 645 | 711 |
| 646 Handle<Object> CodeObject() { return code_object_; } | 712 Handle<Object> CodeObject() { return code_object_; } |
| 647 | 713 |
| 648 | 714 |
| 649 // --------------------------------------------------------------------------- | 715 // --------------------------------------------------------------------------- |
| 650 // StatsCounter support | 716 // StatsCounter support |
| 651 | 717 |
| 652 void SetCounter(StatsCounter* counter, int value, | 718 void SetCounter(StatsCounter* counter, int value, |
| 653 Register scratch1, Register scratch2); | 719 Register scratch1, Register scratch2); |
| 654 void IncrementCounter(StatsCounter* counter, int value, | 720 void IncrementCounter(StatsCounter* counter, int value, |
| 655 Register scratch1, Register scratch2); | 721 Register scratch1, Register scratch2); |
| 656 void DecrementCounter(StatsCounter* counter, int value, | 722 void DecrementCounter(StatsCounter* counter, int value, |
| 657 Register scratch1, Register scratch2); | 723 Register scratch1, Register scratch2); |
| 658 | 724 |
| 659 | 725 |
| 660 // --------------------------------------------------------------------------- | 726 // --------------------------------------------------------------------------- |
| 661 // Debugging | 727 // Debugging |
| 662 | 728 |
| 663 // Calls Abort(msg) if the condition cc is not satisfied. | 729 // Calls Abort(msg) if the condition cond is not satisfied. |
| 664 // Use --debug_code to enable. | 730 // Use --debug_code to enable. |
| 665 void Assert(Condition cc, const char* msg); | 731 void Assert(Condition cond, const char* msg); |
| 666 void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index); | 732 void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index); |
| 667 void AssertFastElements(Register elements); | 733 void AssertFastElements(Register elements); |
| 668 | 734 |
| 669 // Like Assert(), but always enabled. | 735 // Like Assert(), but always enabled. |
| 670 void Check(Condition cc, const char* msg); | 736 void Check(Condition cond, const char* msg); |
| 671 | 737 |
| 672 // Print a message to stdout and abort execution. | 738 // Print a message to stdout and abort execution. |
| 673 void Abort(const char* msg); | 739 void Abort(const char* msg); |
| 674 | 740 |
| 675 // Verify restrictions about code generated in stubs. | 741 // Verify restrictions about code generated in stubs. |
| 676 void set_generating_stub(bool value) { generating_stub_ = value; } | 742 void set_generating_stub(bool value) { generating_stub_ = value; } |
| 677 bool generating_stub() { return generating_stub_; } | 743 bool generating_stub() { return generating_stub_; } |
| 678 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } | 744 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } |
| 679 bool allow_stub_calls() { return allow_stub_calls_; } | 745 bool allow_stub_calls() { return allow_stub_calls_; } |
| 680 | 746 |
| 681 // --------------------------------------------------------------------------- | 747 // --------------------------------------------------------------------------- |
| 748 // Number utilities |
| 749 |
| 750 // Check whether the value of reg is a power of two and not zero. If not |
| 751 // control continues at the label not_power_of_two. If reg is a power of two |
| 752 // the register scratch contains the value of (reg - 1) when control falls |
| 753 // through. |
| 754 void JumpIfNotPowerOfTwoOrZero(Register reg, |
| 755 Register scratch, |
| 756 Label* not_power_of_two_or_zero); |
| 757 |
| 758 // --------------------------------------------------------------------------- |
| 682 // Smi utilities | 759 // Smi utilities |
| 683 | 760 |
| 684 void SmiTag(Register reg, SBit s = LeaveCC) { | 761 void SmiTag(Register reg, SBit s = LeaveCC) { |
| 685 add(reg, reg, Operand(reg), s); | 762 add(reg, reg, Operand(reg), s); |
| 686 } | 763 } |
| 764 void SmiTag(Register dst, Register src, SBit s = LeaveCC) { |
| 765 add(dst, src, Operand(src), s); |
| 766 } |
| 767 |
| 768 // Try to convert int32 to smi. If the value is to large, preserve |
| 769 // the original value and jump to not_a_smi. Destroys scratch and |
| 770 // sets flags. |
| 771 void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) { |
| 772 mov(scratch, reg); |
| 773 SmiTag(scratch, SetCC); |
| 774 b(vs, not_a_smi); |
| 775 mov(reg, scratch); |
| 776 } |
| 687 | 777 |
| 688 void SmiUntag(Register reg) { | 778 void SmiUntag(Register reg) { |
| 689 mov(reg, Operand(reg, ASR, kSmiTagSize)); | 779 mov(reg, Operand(reg, ASR, kSmiTagSize)); |
| 690 } | 780 } |
| 781 void SmiUntag(Register dst, Register src) { |
| 782 mov(dst, Operand(src, ASR, kSmiTagSize)); |
| 783 } |
| 691 | 784 |
| 785 // Jump the register contains a smi. |
| 786 inline void JumpIfSmi(Register value, Label* smi_label) { |
| 787 tst(value, Operand(kSmiTagMask)); |
| 788 b(eq, smi_label); |
| 789 } |
| 790 // Jump if either of the registers contain a non-smi. |
| 791 inline void JumpIfNotSmi(Register value, Label* not_smi_label) { |
| 792 tst(value, Operand(kSmiTagMask)); |
| 793 b(ne, not_smi_label); |
| 794 } |
| 692 // Jump if either of the registers contain a non-smi. | 795 // Jump if either of the registers contain a non-smi. |
| 693 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); | 796 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); |
| 694 // Jump if either of the registers contain a smi. | 797 // Jump if either of the registers contain a smi. |
| 695 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi); | 798 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi); |
| 696 | 799 |
| 697 // Abort execution if argument is a smi. Used in debug code. | 800 // Abort execution if argument is a smi. Used in debug code. |
| 698 void AbortIfSmi(Register object); | 801 void AbortIfSmi(Register object); |
| 802 void AbortIfNotSmi(Register object); |
| 803 |
| 804 // Abort execution if argument is a string. Used in debug code. |
| 805 void AbortIfNotString(Register object); |
| 806 |
| 807 // Abort execution if argument is not the root value with the given index. |
| 808 void AbortIfNotRootValue(Register src, |
| 809 Heap::RootListIndex root_value_index, |
| 810 const char* message); |
| 811 |
| 812 // --------------------------------------------------------------------------- |
| 813 // HeapNumber utilities |
| 814 |
| 815 void JumpIfNotHeapNumber(Register object, |
| 816 Register heap_number_map, |
| 817 Register scratch, |
| 818 Label* on_not_heap_number); |
| 699 | 819 |
| 700 // --------------------------------------------------------------------------- | 820 // --------------------------------------------------------------------------- |
| 701 // String utilities | 821 // String utilities |
| 702 | 822 |
| 703 // Checks if both objects are sequential ASCII strings and jumps to label | 823 // Checks if both objects are sequential ASCII strings and jumps to label |
| 704 // if either is not. Assumes that neither object is a smi. | 824 // if either is not. Assumes that neither object is a smi. |
| 705 void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1, | 825 void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1, |
| 706 Register object2, | 826 Register object2, |
| 707 Register scratch1, | 827 Register scratch1, |
| 708 Register scratch2, | 828 Register scratch2, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 725 Register scratch2, | 845 Register scratch2, |
| 726 Label* failure); | 846 Label* failure); |
| 727 | 847 |
| 728 // Check if instance type is sequential ASCII string and jump to label if | 848 // Check if instance type is sequential ASCII string and jump to label if |
| 729 // it is not. | 849 // it is not. |
| 730 void JumpIfInstanceTypeIsNotSequentialAscii(Register type, | 850 void JumpIfInstanceTypeIsNotSequentialAscii(Register type, |
| 731 Register scratch, | 851 Register scratch, |
| 732 Label* failure); | 852 Label* failure); |
| 733 | 853 |
| 734 | 854 |
| 855 // --------------------------------------------------------------------------- |
| 856 // Patching helpers. |
| 857 |
| 858 // Get the location of a relocated constant (its address in the constant pool) |
| 859 // from its load site. |
| 860 void GetRelocatedValueLocation(Register ldr_location, |
| 861 Register result); |
| 862 |
| 863 |
| 735 private: | 864 private: |
| 736 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); | 865 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); |
| 737 void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); | 866 void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); |
| 738 | 867 |
| 739 // Helper functions for generating invokes. | 868 // Helper functions for generating invokes. |
| 740 void InvokePrologue(const ParameterCount& expected, | 869 void InvokePrologue(const ParameterCount& expected, |
| 741 const ParameterCount& actual, | 870 const ParameterCount& actual, |
| 742 Handle<Code> code_constant, | 871 Handle<Code> code_constant, |
| 743 Register code_reg, | 872 Register code_reg, |
| 744 Label* done, | 873 Label* done, |
| 745 InvokeFlag flag); | 874 InvokeFlag flag, |
| 875 PostCallGenerator* post_call_generator = NULL); |
| 746 | 876 |
| 747 // Activation support. | 877 // Activation support. |
| 748 void EnterFrame(StackFrame::Type type); | 878 void EnterFrame(StackFrame::Type type); |
| 749 void LeaveFrame(StackFrame::Type type); | 879 void LeaveFrame(StackFrame::Type type); |
| 750 | 880 |
| 751 void InitializeNewString(Register string, | 881 void InitializeNewString(Register string, |
| 752 Register length, | 882 Register length, |
| 753 Heap::RootListIndex map_index, | 883 Heap::RootListIndex map_index, |
| 754 Register scratch1, | 884 Register scratch1, |
| 755 Register scratch2); | 885 Register scratch2); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 769 // an assertion to fail. | 899 // an assertion to fail. |
| 770 class CodePatcher { | 900 class CodePatcher { |
| 771 public: | 901 public: |
| 772 CodePatcher(byte* address, int instructions); | 902 CodePatcher(byte* address, int instructions); |
| 773 virtual ~CodePatcher(); | 903 virtual ~CodePatcher(); |
| 774 | 904 |
| 775 // Macro assembler to emit code. | 905 // Macro assembler to emit code. |
| 776 MacroAssembler* masm() { return &masm_; } | 906 MacroAssembler* masm() { return &masm_; } |
| 777 | 907 |
| 778 // Emit an instruction directly. | 908 // Emit an instruction directly. |
| 779 void Emit(Instr x); | 909 void Emit(Instr instr); |
| 780 | 910 |
| 781 // Emit an address directly. | 911 // Emit an address directly. |
| 782 void Emit(Address addr); | 912 void Emit(Address addr); |
| 783 | 913 |
| 914 // Emit the condition part of an instruction leaving the rest of the current |
| 915 // instruction unchanged. |
| 916 void EmitCondition(Condition cond); |
| 917 |
| 784 private: | 918 private: |
| 785 byte* address_; // The address of the code being patched. | 919 byte* address_; // The address of the code being patched. |
| 786 int instructions_; // Number of instructions of the expected patch size. | 920 int instructions_; // Number of instructions of the expected patch size. |
| 787 int size_; // Number of bytes of the expected patch size. | 921 int size_; // Number of bytes of the expected patch size. |
| 788 MacroAssembler masm_; // Macro assembler used to generate the code. | 922 MacroAssembler masm_; // Macro assembler used to generate the code. |
| 789 }; | 923 }; |
| 790 #endif // ENABLE_DEBUGGER_SUPPORT | 924 #endif // ENABLE_DEBUGGER_SUPPORT |
| 791 | 925 |
| 792 | 926 |
| 793 // Helper class for generating code or data associated with the code | 927 // Helper class for generating code or data associated with the code |
| (...skipping 26 matching lines...) Expand all Loading... |
| 820 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) | 954 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) |
| 821 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> | 955 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> |
| 822 #else | 956 #else |
| 823 #define ACCESS_MASM(masm) masm-> | 957 #define ACCESS_MASM(masm) masm-> |
| 824 #endif | 958 #endif |
| 825 | 959 |
| 826 | 960 |
| 827 } } // namespace v8::internal | 961 } } // namespace v8::internal |
| 828 | 962 |
| 829 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ | 963 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ |
| OLD | NEW |