| 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 16 matching lines...) Expand all Loading... |
| 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. | 36 // Forward declaration. |
| 37 class PostCallGenerator; | 37 class CallWrapper; |
| 38 | 38 |
| 39 // ---------------------------------------------------------------------------- | 39 // ---------------------------------------------------------------------------- |
| 40 // Static helper functions | 40 // Static helper functions |
| 41 | 41 |
| 42 // Generate a MemOperand for loading a field from an object. | 42 // Generate a MemOperand for loading a field from an object. |
| 43 static inline MemOperand FieldMemOperand(Register object, int offset) { | 43 static inline MemOperand FieldMemOperand(Register object, int offset) { |
| 44 return MemOperand(object, offset - kHeapObjectTag); | 44 return MemOperand(object, offset - kHeapObjectTag); |
| 45 } | 45 } |
| 46 | 46 |
| 47 | 47 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 | 89 |
| 90 // MacroAssembler implements a collection of frequently used macros. | 90 // MacroAssembler implements a collection of frequently used macros. |
| 91 class MacroAssembler: public Assembler { | 91 class MacroAssembler: public Assembler { |
| 92 public: | 92 public: |
| 93 MacroAssembler(void* buffer, int size); | 93 MacroAssembler(void* buffer, int size); |
| 94 | 94 |
| 95 // Jump, Call, and Ret pseudo instructions implementing inter-working. | 95 // Jump, Call, and Ret pseudo instructions implementing inter-working. |
| 96 void Jump(Register target, Condition cond = al); | 96 void Jump(Register target, Condition cond = al); |
| 97 void Jump(byte* target, RelocInfo::Mode rmode, Condition cond = al); | 97 void Jump(byte* target, RelocInfo::Mode rmode, Condition cond = al); |
| 98 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); | 98 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); |
| 99 int CallSize(Register target, Condition cond = al); |
| 99 void Call(Register target, Condition cond = al); | 100 void Call(Register target, Condition cond = al); |
| 101 int CallSize(byte* target, RelocInfo::Mode rmode, Condition cond = al); |
| 100 void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al); | 102 void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al); |
| 103 int CallSize(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); |
| 101 void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); | 104 void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); |
| 102 void Ret(Condition cond = al); | 105 void Ret(Condition cond = al); |
| 103 | 106 |
| 104 // Emit code to discard a non-negative number of pointer-sized elements | 107 // Emit code to discard a non-negative number of pointer-sized elements |
| 105 // from the stack, clobbering only the sp register. | 108 // from the stack, clobbering only the sp register. |
| 106 void Drop(int count, Condition cond = al); | 109 void Drop(int count, Condition cond = al); |
| 107 | 110 |
| 108 void Ret(int drop, Condition cond = al); | 111 void Ret(int drop, Condition cond = al); |
| 109 | 112 |
| 110 // Swap two registers. If the scratch register is omitted then a slightly | 113 // Swap two registers. If the scratch register is omitted then a slightly |
| 111 // less efficient form using xor instead of mov is emitted. | 114 // less efficient form using xor instead of mov is emitted. |
| 112 void Swap(Register reg1, | 115 void Swap(Register reg1, |
| 113 Register reg2, | 116 Register reg2, |
| 114 Register scratch = no_reg, | 117 Register scratch = no_reg, |
| 115 Condition cond = al); | 118 Condition cond = al); |
| 116 | 119 |
| 117 | 120 |
| 118 void And(Register dst, Register src1, const Operand& src2, | 121 void And(Register dst, Register src1, const Operand& src2, |
| 119 Condition cond = al); | 122 Condition cond = al); |
| 120 void Ubfx(Register dst, Register src, int lsb, int width, | 123 void Ubfx(Register dst, Register src, int lsb, int width, |
| 121 Condition cond = al); | 124 Condition cond = al); |
| 122 void Sbfx(Register dst, Register src, int lsb, int width, | 125 void Sbfx(Register dst, Register src, int lsb, int width, |
| 123 Condition cond = al); | 126 Condition cond = al); |
| 127 // The scratch register is not used for ARMv7. |
| 128 // scratch can be the same register as src (in which case it is trashed), but |
| 129 // not the same as dst. |
| 130 void Bfi(Register dst, |
| 131 Register src, |
| 132 Register scratch, |
| 133 int lsb, |
| 134 int width, |
| 135 Condition cond = al); |
| 124 void Bfc(Register dst, int lsb, int width, Condition cond = al); | 136 void Bfc(Register dst, int lsb, int width, Condition cond = al); |
| 125 void Usat(Register dst, int satpos, const Operand& src, | 137 void Usat(Register dst, int satpos, const Operand& src, |
| 126 Condition cond = al); | 138 Condition cond = al); |
| 127 | 139 |
| 128 void Call(Label* target); | 140 void Call(Label* target); |
| 129 void Move(Register dst, Handle<Object> value); | 141 void Move(Register dst, Handle<Object> value); |
| 130 // May do nothing if the registers are identical. | 142 // May do nothing if the registers are identical. |
| 131 void Move(Register dst, Register src); | 143 void Move(Register dst, Register src); |
| 132 // Jumps to the label at the index given by the Smi in "index". | 144 // Jumps to the label at the index given by the Smi in "index". |
| 133 void SmiJumpTable(Register index, Vector<Label*> targets); | 145 void SmiJumpTable(Register index, Vector<Label*> targets); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 } else { | 240 } else { |
| 229 stm(db_w, sp, src1.bit() | src2.bit(), cond); | 241 stm(db_w, sp, src1.bit() | src2.bit(), cond); |
| 230 Push(src3, src4, cond); | 242 Push(src3, src4, cond); |
| 231 } | 243 } |
| 232 } else { | 244 } else { |
| 233 str(src1, MemOperand(sp, 4, NegPreIndex), cond); | 245 str(src1, MemOperand(sp, 4, NegPreIndex), cond); |
| 234 Push(src2, src3, src4, cond); | 246 Push(src2, src3, src4, cond); |
| 235 } | 247 } |
| 236 } | 248 } |
| 237 | 249 |
| 250 // Pop two registers. Pops rightmost register first (from lower address). |
| 251 void Pop(Register src1, Register src2, Condition cond = al) { |
| 252 ASSERT(!src1.is(src2)); |
| 253 if (src1.code() > src2.code()) { |
| 254 ldm(ia_w, sp, src1.bit() | src2.bit(), cond); |
| 255 } else { |
| 256 ldr(src2, MemOperand(sp, 4, PostIndex), cond); |
| 257 ldr(src1, MemOperand(sp, 4, PostIndex), cond); |
| 258 } |
| 259 } |
| 260 |
| 238 // Push and pop the registers that can hold pointers, as defined by the | 261 // Push and pop the registers that can hold pointers, as defined by the |
| 239 // RegList constant kSafepointSavedRegisters. | 262 // RegList constant kSafepointSavedRegisters. |
| 240 void PushSafepointRegisters(); | 263 void PushSafepointRegisters(); |
| 241 void PopSafepointRegisters(); | 264 void PopSafepointRegisters(); |
| 242 void PushSafepointRegistersAndDoubles(); | 265 void PushSafepointRegistersAndDoubles(); |
| 243 void PopSafepointRegistersAndDoubles(); | 266 void PopSafepointRegistersAndDoubles(); |
| 244 void StoreToSafepointRegisterSlot(Register reg); | 267 // Store value in register src in the safepoint stack slot for |
| 245 void StoreToSafepointRegistersAndDoublesSlot(Register reg); | 268 // register dst. |
| 246 void LoadFromSafepointRegisterSlot(Register reg); | 269 void StoreToSafepointRegisterSlot(Register src, Register dst); |
| 247 static int SafepointRegisterStackIndex(int reg_code); | 270 void StoreToSafepointRegistersAndDoublesSlot(Register src, Register dst); |
| 248 static MemOperand SafepointRegisterSlot(Register reg); | 271 // Load the value of the src register from its safepoint stack slot |
| 249 static MemOperand SafepointRegistersAndDoublesSlot(Register reg); | 272 // into register dst. |
| 273 void LoadFromSafepointRegisterSlot(Register dst, Register src); |
| 250 | 274 |
| 251 // Load two consecutive registers with two consecutive memory locations. | 275 // Load two consecutive registers with two consecutive memory locations. |
| 252 void Ldrd(Register dst1, | 276 void Ldrd(Register dst1, |
| 253 Register dst2, | 277 Register dst2, |
| 254 const MemOperand& src, | 278 const MemOperand& src, |
| 255 Condition cond = al); | 279 Condition cond = al); |
| 256 | 280 |
| 257 // Store two consecutive registers to two consecutive memory locations. | 281 // Store two consecutive registers to two consecutive memory locations. |
| 258 void Strd(Register src1, | 282 void Strd(Register src1, |
| 259 Register src2, | 283 Register src2, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 Register scratch); | 340 Register scratch); |
| 317 | 341 |
| 318 // --------------------------------------------------------------------------- | 342 // --------------------------------------------------------------------------- |
| 319 // JavaScript invokes | 343 // JavaScript invokes |
| 320 | 344 |
| 321 // Invoke the JavaScript function code by either calling or jumping. | 345 // Invoke the JavaScript function code by either calling or jumping. |
| 322 void InvokeCode(Register code, | 346 void InvokeCode(Register code, |
| 323 const ParameterCount& expected, | 347 const ParameterCount& expected, |
| 324 const ParameterCount& actual, | 348 const ParameterCount& actual, |
| 325 InvokeFlag flag, | 349 InvokeFlag flag, |
| 326 PostCallGenerator* post_call_generator = NULL); | 350 CallWrapper* call_wrapper = NULL); |
| 327 | 351 |
| 328 void InvokeCode(Handle<Code> code, | 352 void InvokeCode(Handle<Code> code, |
| 329 const ParameterCount& expected, | 353 const ParameterCount& expected, |
| 330 const ParameterCount& actual, | 354 const ParameterCount& actual, |
| 331 RelocInfo::Mode rmode, | 355 RelocInfo::Mode rmode, |
| 332 InvokeFlag flag); | 356 InvokeFlag flag); |
| 333 | 357 |
| 334 // Invoke the JavaScript function in the given register. Changes the | 358 // Invoke the JavaScript function in the given register. Changes the |
| 335 // current context to the context in the function before invoking. | 359 // current context to the context in the function before invoking. |
| 336 void InvokeFunction(Register function, | 360 void InvokeFunction(Register function, |
| 337 const ParameterCount& actual, | 361 const ParameterCount& actual, |
| 338 InvokeFlag flag, | 362 InvokeFlag flag, |
| 339 PostCallGenerator* post_call_generator = NULL); | 363 CallWrapper* call_wrapper = NULL); |
| 340 | 364 |
| 341 void InvokeFunction(JSFunction* function, | 365 void InvokeFunction(JSFunction* function, |
| 342 const ParameterCount& actual, | 366 const ParameterCount& actual, |
| 343 InvokeFlag flag); | 367 InvokeFlag flag); |
| 344 | 368 |
| 345 void IsObjectJSObjectType(Register heap_object, | 369 void IsObjectJSObjectType(Register heap_object, |
| 346 Register map, | 370 Register map, |
| 347 Register scratch, | 371 Register scratch, |
| 348 Label* fail); | 372 Label* fail); |
| 349 | 373 |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 void AllocateHeapNumberWithValue(Register result, | 514 void AllocateHeapNumberWithValue(Register result, |
| 491 DwVfpRegister value, | 515 DwVfpRegister value, |
| 492 Register scratch1, | 516 Register scratch1, |
| 493 Register scratch2, | 517 Register scratch2, |
| 494 Register heap_number_map, | 518 Register heap_number_map, |
| 495 Label* gc_required); | 519 Label* gc_required); |
| 496 | 520 |
| 497 // Copies a fixed number of fields of heap objects from src to dst. | 521 // Copies a fixed number of fields of heap objects from src to dst. |
| 498 void CopyFields(Register dst, Register src, RegList temps, int field_count); | 522 void CopyFields(Register dst, Register src, RegList temps, int field_count); |
| 499 | 523 |
| 524 // Copies a number of bytes from src to dst. All registers are clobbered. On |
| 525 // exit src and dst will point to the place just after where the last byte was |
| 526 // read or written and length will be zero. |
| 527 void CopyBytes(Register src, |
| 528 Register dst, |
| 529 Register length, |
| 530 Register scratch); |
| 531 |
| 500 // --------------------------------------------------------------------------- | 532 // --------------------------------------------------------------------------- |
| 501 // Support functions. | 533 // Support functions. |
| 502 | 534 |
| 503 // Try to get function prototype of a function and puts the value in | 535 // Try to get function prototype of a function and puts the value in |
| 504 // the result register. Checks that the function really is a | 536 // the result register. Checks that the function really is a |
| 505 // function and jumps to the miss label if the fast checks fail. The | 537 // function and jumps to the miss label if the fast checks fail. The |
| 506 // function register will be untouched; the other registers may be | 538 // function register will be untouched; the other registers may be |
| 507 // clobbered. | 539 // clobbered. |
| 508 void TryGetFunctionPrototype(Register function, | 540 void TryGetFunctionPrototype(Register function, |
| 509 Register result, | 541 Register result, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 Label* fail, | 574 Label* fail, |
| 543 bool is_heap_object); | 575 bool is_heap_object); |
| 544 | 576 |
| 545 void CheckMap(Register obj, | 577 void CheckMap(Register obj, |
| 546 Register scratch, | 578 Register scratch, |
| 547 Heap::RootListIndex index, | 579 Heap::RootListIndex index, |
| 548 Label* fail, | 580 Label* fail, |
| 549 bool is_heap_object); | 581 bool is_heap_object); |
| 550 | 582 |
| 551 | 583 |
| 584 // Compare the object in a register to a value from the root list. |
| 585 // Uses the ip register as scratch. |
| 586 void CompareRoot(Register obj, Heap::RootListIndex index); |
| 587 |
| 588 |
| 552 // Load and check the instance type of an object for being a string. | 589 // Load and check the instance type of an object for being a string. |
| 553 // Loads the type into the second argument register. | 590 // Loads the type into the second argument register. |
| 554 // Returns a condition that will be enabled if the object was a string. | 591 // Returns a condition that will be enabled if the object was a string. |
| 555 Condition IsObjectStringType(Register obj, | 592 Condition IsObjectStringType(Register obj, |
| 556 Register type) { | 593 Register type) { |
| 557 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset)); | 594 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset)); |
| 558 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset)); | 595 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset)); |
| 559 tst(type, Operand(kIsNotStringMask)); | 596 tst(type, Operand(kIsNotStringMask)); |
| 560 ASSERT_EQ(0, kStringTag); | 597 ASSERT_EQ(0, kStringTag); |
| 561 return eq; | 598 return eq; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 // dest. If the HeapNumber does not fit into a 32bits signed integer branch | 643 // dest. If the HeapNumber does not fit into a 32bits signed integer branch |
| 607 // to not_int32 label. If VFP3 is available double_scratch is used but not | 644 // to not_int32 label. If VFP3 is available double_scratch is used but not |
| 608 // scratch2. | 645 // scratch2. |
| 609 void ConvertToInt32(Register source, | 646 void ConvertToInt32(Register source, |
| 610 Register dest, | 647 Register dest, |
| 611 Register scratch, | 648 Register scratch, |
| 612 Register scratch2, | 649 Register scratch2, |
| 613 DwVfpRegister double_scratch, | 650 DwVfpRegister double_scratch, |
| 614 Label *not_int32); | 651 Label *not_int32); |
| 615 | 652 |
| 653 // Truncates a double using a specific rounding mode. |
| 654 // Clears the z flag (ne condition) if an overflow occurs. |
| 655 // If exact_conversion is true, the z flag is also cleared if the conversion |
| 656 // was inexact, ie. if the double value could not be converted exactly |
| 657 // to a 32bit integer. |
| 658 void EmitVFPTruncate(VFPRoundingMode rounding_mode, |
| 659 SwVfpRegister result, |
| 660 DwVfpRegister double_input, |
| 661 Register scratch1, |
| 662 Register scratch2, |
| 663 CheckForInexactConversion check |
| 664 = kDontCheckForInexactConversion); |
| 665 |
| 666 // Helper for EmitECMATruncate. |
| 667 // This will truncate a floating-point value outside of the singed 32bit |
| 668 // integer range to a 32bit signed integer. |
| 669 // Expects the double value loaded in input_high and input_low. |
| 670 // Exits with the answer in 'result'. |
| 671 // Note that this code does not work for values in the 32bit range! |
| 672 void EmitOutOfInt32RangeTruncate(Register result, |
| 673 Register input_high, |
| 674 Register input_low, |
| 675 Register scratch); |
| 676 |
| 677 // Performs a truncating conversion of a floating point number as used by |
| 678 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. |
| 679 // Exits with 'result' holding the answer and all other registers clobbered. |
| 680 void EmitECMATruncate(Register result, |
| 681 DwVfpRegister double_input, |
| 682 SwVfpRegister single_scratch, |
| 683 Register scratch, |
| 684 Register scratch2, |
| 685 Register scratch3); |
| 686 |
| 616 // Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz | 687 // Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz |
| 617 // instruction. On pre-ARM5 hardware this routine gives the wrong answer | 688 // instruction. On pre-ARM5 hardware this routine gives the wrong answer |
| 618 // for 0 (31 instead of 32). Source and scratch can be the same in which case | 689 // for 0 (31 instead of 32). Source and scratch can be the same in which case |
| 619 // the source is clobbered. Source and zeros can also be the same in which | 690 // the source is clobbered. Source and zeros can also be the same in which |
| 620 // case scratch should be a different register. | 691 // case scratch should be a different register. |
| 621 void CountLeadingZeros(Register zeros, | 692 void CountLeadingZeros(Register zeros, |
| 622 Register source, | 693 Register source, |
| 623 Register scratch); | 694 Register scratch); |
| 624 | 695 |
| 625 // --------------------------------------------------------------------------- | 696 // --------------------------------------------------------------------------- |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 void PrepareCallCFunction(int num_arguments, Register scratch); | 748 void PrepareCallCFunction(int num_arguments, Register scratch); |
| 678 | 749 |
| 679 // Calls a C function and cleans up the space for arguments allocated | 750 // Calls a C function and cleans up the space for arguments allocated |
| 680 // by PrepareCallCFunction. The called function is not allowed to trigger a | 751 // by PrepareCallCFunction. The called function is not allowed to trigger a |
| 681 // garbage collection, since that might move the code and invalidate the | 752 // garbage collection, since that might move the code and invalidate the |
| 682 // return address (unless this is somehow accounted for by the called | 753 // return address (unless this is somehow accounted for by the called |
| 683 // function). | 754 // function). |
| 684 void CallCFunction(ExternalReference function, int num_arguments); | 755 void CallCFunction(ExternalReference function, int num_arguments); |
| 685 void CallCFunction(Register function, int num_arguments); | 756 void CallCFunction(Register function, int num_arguments); |
| 686 | 757 |
| 758 void GetCFunctionDoubleResult(const DoubleRegister dst); |
| 759 |
| 687 // Calls an API function. Allocates HandleScope, extracts returned value | 760 // Calls an API function. Allocates HandleScope, extracts returned value |
| 688 // from handle and propagates exceptions. Restores context. | 761 // from handle and propagates exceptions. Restores context. |
| 689 // stack_space - space to be unwound on exit (includes the call js | 762 // stack_space - space to be unwound on exit (includes the call js |
| 690 // arguments space and the additional space allocated for the fast call). | 763 // arguments space and the additional space allocated for the fast call). |
| 691 MaybeObject* TryCallApiFunctionAndReturn(ApiFunction* function, | 764 MaybeObject* TryCallApiFunctionAndReturn(ExternalReference function, |
| 692 int stack_space); | 765 int stack_space); |
| 693 | 766 |
| 694 // Jump to a runtime routine. | 767 // Jump to a runtime routine. |
| 695 void JumpToExternalReference(const ExternalReference& builtin); | 768 void JumpToExternalReference(const ExternalReference& builtin); |
| 696 | 769 |
| 697 MaybeObject* TryJumpToExternalReference(const ExternalReference& ext); | 770 MaybeObject* TryJumpToExternalReference(const ExternalReference& ext); |
| 698 | 771 |
| 699 // Invoke specified builtin JavaScript function. Adds an entry to | 772 // Invoke specified builtin JavaScript function. Adds an entry to |
| 700 // the unresolved list if the name does not resolve. | 773 // the unresolved list if the name does not resolve. |
| 701 void InvokeBuiltin(Builtins::JavaScript id, | 774 void InvokeBuiltin(Builtins::JavaScript id, |
| 702 InvokeJSFlags flags, | 775 InvokeJSFlags flags, |
| 703 PostCallGenerator* post_call_generator = NULL); | 776 CallWrapper* call_wrapper = NULL); |
| 704 | 777 |
| 705 // Store the code object for the given builtin in the target register and | 778 // Store the code object for the given builtin in the target register and |
| 706 // setup the function in r1. | 779 // setup the function in r1. |
| 707 void GetBuiltinEntry(Register target, Builtins::JavaScript id); | 780 void GetBuiltinEntry(Register target, Builtins::JavaScript id); |
| 708 | 781 |
| 709 // Store the function for the given builtin in the target register. | 782 // Store the function for the given builtin in the target register. |
| 710 void GetBuiltinFunction(Register target, Builtins::JavaScript id); | 783 void GetBuiltinFunction(Register target, Builtins::JavaScript id); |
| 711 | 784 |
| 712 Handle<Object> CodeObject() { return code_object_; } | 785 Handle<Object> CodeObject() { return code_object_; } |
| 713 | 786 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 768 // Try to convert int32 to smi. If the value is to large, preserve | 841 // 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 | 842 // the original value and jump to not_a_smi. Destroys scratch and |
| 770 // sets flags. | 843 // sets flags. |
| 771 void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) { | 844 void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) { |
| 772 mov(scratch, reg); | 845 mov(scratch, reg); |
| 773 SmiTag(scratch, SetCC); | 846 SmiTag(scratch, SetCC); |
| 774 b(vs, not_a_smi); | 847 b(vs, not_a_smi); |
| 775 mov(reg, scratch); | 848 mov(reg, scratch); |
| 776 } | 849 } |
| 777 | 850 |
| 778 void SmiUntag(Register reg) { | 851 void SmiUntag(Register reg, SBit s = LeaveCC) { |
| 779 mov(reg, Operand(reg, ASR, kSmiTagSize)); | 852 mov(reg, Operand(reg, ASR, kSmiTagSize), s); |
| 780 } | 853 } |
| 781 void SmiUntag(Register dst, Register src) { | 854 void SmiUntag(Register dst, Register src, SBit s = LeaveCC) { |
| 782 mov(dst, Operand(src, ASR, kSmiTagSize)); | 855 mov(dst, Operand(src, ASR, kSmiTagSize), s); |
| 783 } | 856 } |
| 784 | 857 |
| 785 // Jump the register contains a smi. | 858 // Jump the register contains a smi. |
| 786 inline void JumpIfSmi(Register value, Label* smi_label) { | 859 inline void JumpIfSmi(Register value, Label* smi_label) { |
| 787 tst(value, Operand(kSmiTagMask)); | 860 tst(value, Operand(kSmiTagMask)); |
| 788 b(eq, smi_label); | 861 b(eq, smi_label); |
| 789 } | 862 } |
| 790 // Jump if either of the registers contain a non-smi. | 863 // Jump if either of the registers contain a non-smi. |
| 791 inline void JumpIfNotSmi(Register value, Label* not_smi_label) { | 864 inline void JumpIfNotSmi(Register value, Label* not_smi_label) { |
| 792 tst(value, Operand(kSmiTagMask)); | 865 tst(value, Operand(kSmiTagMask)); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 // Patching helpers. | 929 // Patching helpers. |
| 857 | 930 |
| 858 // Get the location of a relocated constant (its address in the constant pool) | 931 // Get the location of a relocated constant (its address in the constant pool) |
| 859 // from its load site. | 932 // from its load site. |
| 860 void GetRelocatedValueLocation(Register ldr_location, | 933 void GetRelocatedValueLocation(Register ldr_location, |
| 861 Register result); | 934 Register result); |
| 862 | 935 |
| 863 | 936 |
| 864 private: | 937 private: |
| 865 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); | 938 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); |
| 939 int CallSize(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); |
| 866 void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); | 940 void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); |
| 867 | 941 |
| 868 // Helper functions for generating invokes. | 942 // Helper functions for generating invokes. |
| 869 void InvokePrologue(const ParameterCount& expected, | 943 void InvokePrologue(const ParameterCount& expected, |
| 870 const ParameterCount& actual, | 944 const ParameterCount& actual, |
| 871 Handle<Code> code_constant, | 945 Handle<Code> code_constant, |
| 872 Register code_reg, | 946 Register code_reg, |
| 873 Label* done, | 947 Label* done, |
| 874 InvokeFlag flag, | 948 InvokeFlag flag, |
| 875 PostCallGenerator* post_call_generator = NULL); | 949 CallWrapper* call_wrapper = NULL); |
| 876 | 950 |
| 877 // Activation support. | 951 // Activation support. |
| 878 void EnterFrame(StackFrame::Type type); | 952 void EnterFrame(StackFrame::Type type); |
| 879 void LeaveFrame(StackFrame::Type type); | 953 void LeaveFrame(StackFrame::Type type); |
| 880 | 954 |
| 881 void InitializeNewString(Register string, | 955 void InitializeNewString(Register string, |
| 882 Register length, | 956 Register length, |
| 883 Heap::RootListIndex map_index, | 957 Heap::RootListIndex map_index, |
| 884 Register scratch1, | 958 Register scratch1, |
| 885 Register scratch2); | 959 Register scratch2); |
| 886 | 960 |
| 961 // Compute memory operands for safepoint stack slots. |
| 962 static int SafepointRegisterStackIndex(int reg_code); |
| 963 MemOperand SafepointRegisterSlot(Register reg); |
| 964 MemOperand SafepointRegistersAndDoublesSlot(Register reg); |
| 965 |
| 887 bool generating_stub_; | 966 bool generating_stub_; |
| 888 bool allow_stub_calls_; | 967 bool allow_stub_calls_; |
| 889 // This handle will be patched with the code object on installation. | 968 // This handle will be patched with the code object on installation. |
| 890 Handle<Object> code_object_; | 969 Handle<Object> code_object_; |
| 970 |
| 971 // Needs access to SafepointRegisterStackIndex for optimized frame |
| 972 // traversal. |
| 973 friend class OptimizedFrame; |
| 891 }; | 974 }; |
| 892 | 975 |
| 893 | 976 |
| 894 #ifdef ENABLE_DEBUGGER_SUPPORT | 977 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 895 // The code patcher is used to patch (typically) small parts of code e.g. for | 978 // The code patcher is used to patch (typically) small parts of code e.g. for |
| 896 // debugging and other types of instrumentation. When using the code patcher | 979 // debugging and other types of instrumentation. When using the code patcher |
| 897 // the exact number of bytes specified must be emitted. It is not legal to emit | 980 // the exact number of bytes specified must be emitted. It is not legal to emit |
| 898 // relocation information. If any of these constraints are violated it causes | 981 // relocation information. If any of these constraints are violated it causes |
| 899 // an assertion to fail. | 982 // an assertion to fail. |
| 900 class CodePatcher { | 983 class CodePatcher { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 920 int instructions_; // Number of instructions of the expected patch size. | 1003 int instructions_; // Number of instructions of the expected patch size. |
| 921 int size_; // Number of bytes of the expected patch size. | 1004 int size_; // Number of bytes of the expected patch size. |
| 922 MacroAssembler masm_; // Macro assembler used to generate the code. | 1005 MacroAssembler masm_; // Macro assembler used to generate the code. |
| 923 }; | 1006 }; |
| 924 #endif // ENABLE_DEBUGGER_SUPPORT | 1007 #endif // ENABLE_DEBUGGER_SUPPORT |
| 925 | 1008 |
| 926 | 1009 |
| 927 // Helper class for generating code or data associated with the code | 1010 // Helper class for generating code or data associated with the code |
| 928 // right after a call instruction. As an example this can be used to | 1011 // right after a call instruction. As an example this can be used to |
| 929 // generate safepoint data after calls for crankshaft. | 1012 // generate safepoint data after calls for crankshaft. |
| 930 class PostCallGenerator { | 1013 class CallWrapper { |
| 931 public: | 1014 public: |
| 932 PostCallGenerator() { } | 1015 CallWrapper() { } |
| 933 virtual ~PostCallGenerator() { } | 1016 virtual ~CallWrapper() { } |
| 934 virtual void Generate() = 0; | 1017 // Called just before emitting a call. Argument is the size of the generated |
| 1018 // call code. |
| 1019 virtual void BeforeCall(int call_size) = 0; |
| 1020 // Called just after emitting a call, i.e., at the return site for the call. |
| 1021 virtual void AfterCall() = 0; |
| 935 }; | 1022 }; |
| 936 | 1023 |
| 937 | 1024 |
| 938 // ----------------------------------------------------------------------------- | 1025 // ----------------------------------------------------------------------------- |
| 939 // Static helper functions. | 1026 // Static helper functions. |
| 940 | 1027 |
| 941 static MemOperand ContextOperand(Register context, int index) { | 1028 static MemOperand ContextOperand(Register context, int index) { |
| 942 return MemOperand(context, Context::SlotOffset(index)); | 1029 return MemOperand(context, Context::SlotOffset(index)); |
| 943 } | 1030 } |
| 944 | 1031 |
| 945 | 1032 |
| 946 static inline MemOperand GlobalObjectOperand() { | 1033 static inline MemOperand GlobalObjectOperand() { |
| 947 return ContextOperand(cp, Context::GLOBAL_INDEX); | 1034 return ContextOperand(cp, Context::GLOBAL_INDEX); |
| 948 } | 1035 } |
| 949 | 1036 |
| 950 | 1037 |
| 951 #ifdef GENERATED_CODE_COVERAGE | 1038 #ifdef GENERATED_CODE_COVERAGE |
| 952 #define CODE_COVERAGE_STRINGIFY(x) #x | 1039 #define CODE_COVERAGE_STRINGIFY(x) #x |
| 953 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) | 1040 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) |
| 954 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) | 1041 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) |
| 955 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> | 1042 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> |
| 956 #else | 1043 #else |
| 957 #define ACCESS_MASM(masm) masm-> | 1044 #define ACCESS_MASM(masm) masm-> |
| 958 #endif | 1045 #endif |
| 959 | 1046 |
| 960 | 1047 |
| 961 } } // namespace v8::internal | 1048 } } // namespace v8::internal |
| 962 | 1049 |
| 963 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ | 1050 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ |
| OLD | NEW |