1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_X64_MACRO_ASSEMBLER_X64_H_ 29 #define V8_X64_MACRO_ASSEMBLER_X64_H_ 30 31 #include "assembler.h" 32 #include "frames.h" 33 #include "v8globals.h" 34 35 namespace v8 { 36 namespace internal { 37 38 // Default scratch register used by MacroAssembler (and other code that needs 39 // a spare register). The register isn't callee save, and not used by the 40 // function calling convention. 41 const Register kScratchRegister = { 10 }; // r10. 42 const Register kSmiConstantRegister = { 12 }; // r12 (callee save). 43 const Register kRootRegister = { 13 }; // r13 (callee save). 44 // Value of smi in kSmiConstantRegister. 45 const int kSmiConstantRegisterValue = 1; 46 // Actual value of root register is offset from the root array's start 47 // to take advantage of negitive 8-bit displacement values. 48 const int kRootRegisterBias = 128; 49 50 // Convenience for platform-independent signatures. 51 typedef Operand MemOperand; 52 53 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; 54 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; 55 56 enum SmiOperationConstraint { 57 PRESERVE_SOURCE_REGISTER, 58 BAILOUT_ON_NO_OVERFLOW, 59 BAILOUT_ON_OVERFLOW, 60 NUMBER_OF_CONSTRAINTS 61 }; 62 63 STATIC_ASSERT(NUMBER_OF_CONSTRAINTS <= 8); 64 65 class SmiOperationExecutionMode : public EnumSet<SmiOperationConstraint, byte> { 66 public: 67 SmiOperationExecutionMode() : EnumSet<SmiOperationConstraint, byte>(0) { } 68 explicit SmiOperationExecutionMode(byte bits) 69 : EnumSet<SmiOperationConstraint, byte>(bits) { } 70 }; 71 72 bool AreAliased(Register r1, Register r2, Register r3, Register r4); 73 74 // Forward declaration. 75 class JumpTarget; 76 77 struct SmiIndex { 78 SmiIndex(Register index_register, ScaleFactor scale) 79 : reg(index_register), 80 scale(scale) {} 81 Register reg; 82 ScaleFactor scale; 83 }; 84 85 86 // MacroAssembler implements a collection of frequently used macros. 87 class MacroAssembler: public Assembler { 88 public: 89 // The isolate parameter can be NULL if the macro assembler should 90 // not use isolate-dependent functionality. In this case, it's the 91 // responsibility of the caller to never invoke such function on the 92 // macro assembler. 93 MacroAssembler(Isolate* isolate, void* buffer, int size); 94 95 // Prevent the use of the RootArray during the lifetime of this 96 // scope object. 97 class NoRootArrayScope BASE_EMBEDDED { 98 public: 99 explicit NoRootArrayScope(MacroAssembler* assembler) 100 : variable_(&assembler->root_array_available_), 101 old_value_(assembler->root_array_available_) { 102 assembler->root_array_available_ = false; 103 } 104 ~NoRootArrayScope() { 105 *variable_ = old_value_; 106 } 107 private: 108 bool* variable_; 109 bool old_value_; 110 }; 111 112 // Operand pointing to an external reference. 113 // May emit code to set up the scratch register. The operand is 114 // only guaranteed to be correct as long as the scratch register 115 // isn't changed. 116 // If the operand is used more than once, use a scratch register 117 // that is guaranteed not to be clobbered. 118 Operand ExternalOperand(ExternalReference reference, 119 Register scratch = kScratchRegister); 120 // Loads and stores the value of an external reference. 121 // Special case code for load and store to take advantage of 122 // load_rax/store_rax if possible/necessary. 123 // For other operations, just use: 124 // Operand operand = ExternalOperand(extref); 125 // operation(operand, ..); 126 void Load(Register destination, ExternalReference source); 127 void Store(ExternalReference destination, Register source); 128 // Loads the address of the external reference into the destination 129 // register. 130 void LoadAddress(Register destination, ExternalReference source); 131 // Returns the size of the code generated by LoadAddress. 132 // Used by CallSize(ExternalReference) to find the size of a call. 133 int LoadAddressSize(ExternalReference source); 134 // Pushes the address of the external reference onto the stack. 135 void PushAddress(ExternalReference source); 136 137 // Operations on roots in the root-array. 138 void LoadRoot(Register destination, Heap::RootListIndex index); 139 void StoreRoot(Register source, Heap::RootListIndex index); 140 // Load a root value where the index (or part of it) is variable. 141 // The variable_offset register is added to the fixed_offset value 142 // to get the index into the root-array. 143 void LoadRootIndexed(Register destination, 144 Register variable_offset, 145 int fixed_offset); 146 void CompareRoot(Register with, Heap::RootListIndex index); 147 void CompareRoot(const Operand& with, Heap::RootListIndex index); 148 void PushRoot(Heap::RootListIndex index); 149 150 // These functions do not arrange the registers in any particular order so 151 // they are not useful for calls that can cause a GC. The caller can 152 // exclude up to 3 registers that do not need to be saved and restored. 153 void PushCallerSaved(SaveFPRegsMode fp_mode, 154 Register exclusion1 = no_reg, 155 Register exclusion2 = no_reg, 156 Register exclusion3 = no_reg); 157 void PopCallerSaved(SaveFPRegsMode fp_mode, 158 Register exclusion1 = no_reg, 159 Register exclusion2 = no_reg, 160 Register exclusion3 = no_reg); 161 162 // --------------------------------------------------------------------------- 163 // GC Support 164 165 166 enum RememberedSetFinalAction { 167 kReturnAtEnd, 168 kFallThroughAtEnd 169 }; 170 171 // Record in the remembered set the fact that we have a pointer to new space 172 // at the address pointed to by the addr register. Only works if addr is not 173 // in new space. 174 void RememberedSetHelper(Register object, // Used for debug code. 175 Register addr, 176 Register scratch, 177 SaveFPRegsMode save_fp, 178 RememberedSetFinalAction and_then); 179 180 void CheckPageFlag(Register object, 181 Register scratch, 182 int mask, 183 Condition cc, 184 Label* condition_met, 185 Label::Distance condition_met_distance = Label::kFar); 186 187 void CheckMapDeprecated(Handle<Map> map, 188 Register scratch, 189 Label* if_deprecated); 190 191 // Check if object is in new space. Jumps if the object is not in new space. 192 // The register scratch can be object itself, but scratch will be clobbered. 193 void JumpIfNotInNewSpace(Register object, 194 Register scratch, 195 Label* branch, 196 Label::Distance distance = Label::kFar) { 197 InNewSpace(object, scratch, not_equal, branch, distance); 198 } 199 200 // Check if object is in new space. Jumps if the object is in new space. 201 // The register scratch can be object itself, but it will be clobbered. 202 void JumpIfInNewSpace(Register object, 203 Register scratch, 204 Label* branch, 205 Label::Distance distance = Label::kFar) { 206 InNewSpace(object, scratch, equal, branch, distance); 207 } 208 209 // Check if an object has the black incremental marking color. Also uses rcx! 210 void JumpIfBlack(Register object, 211 Register scratch0, 212 Register scratch1, 213 Label* on_black, 214 Label::Distance on_black_distance = Label::kFar); 215 216 // Detects conservatively whether an object is data-only, i.e. it does need to 217 // be scanned by the garbage collector. 218 void JumpIfDataObject(Register value, 219 Register scratch, 220 Label* not_data_object, 221 Label::Distance not_data_object_distance); 222 223 // Checks the color of an object. If the object is already grey or black 224 // then we just fall through, since it is already live. If it is white and 225 // we can determine that it doesn't need to be scanned, then we just mark it 226 // black and fall through. For the rest we jump to the label so the 227 // incremental marker can fix its assumptions. 228 void EnsureNotWhite(Register object, 229 Register scratch1, 230 Register scratch2, 231 Label* object_is_white_and_not_data, 232 Label::Distance distance); 233 234 // Notify the garbage collector that we wrote a pointer into an object. 235 // |object| is the object being stored into, |value| is the object being 236 // stored. value and scratch registers are clobbered by the operation. 237 // The offset is the offset from the start of the object, not the offset from 238 // the tagged HeapObject pointer. For use with FieldOperand(reg, off). 239 void RecordWriteField( 240 Register object, 241 int offset, 242 Register value, 243 Register scratch, 244 SaveFPRegsMode save_fp, 245 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 246 SmiCheck smi_check = INLINE_SMI_CHECK); 247 248 // As above, but the offset has the tag presubtracted. For use with 249 // Operand(reg, off). 250 void RecordWriteContextSlot( 251 Register context, 252 int offset, 253 Register value, 254 Register scratch, 255 SaveFPRegsMode save_fp, 256 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 257 SmiCheck smi_check = INLINE_SMI_CHECK) { 258 RecordWriteField(context, 259 offset + kHeapObjectTag, 260 value, 261 scratch, 262 save_fp, 263 remembered_set_action, 264 smi_check); 265 } 266 267 // Notify the garbage collector that we wrote a pointer into a fixed array. 268 // |array| is the array being stored into, |value| is the 269 // object being stored. |index| is the array index represented as a non-smi. 270 // All registers are clobbered by the operation RecordWriteArray 271 // filters out smis so it does not update the write barrier if the 272 // value is a smi. 273 void RecordWriteArray( 274 Register array, 275 Register value, 276 Register index, 277 SaveFPRegsMode save_fp, 278 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 279 SmiCheck smi_check = INLINE_SMI_CHECK); 280 281 // For page containing |object| mark region covering |address| 282 // dirty. |object| is the object being stored into, |value| is the 283 // object being stored. The address and value registers are clobbered by the 284 // operation. RecordWrite filters out smis so it does not update 285 // the write barrier if the value is a smi. 286 void RecordWrite( 287 Register object, 288 Register address, 289 Register value, 290 SaveFPRegsMode save_fp, 291 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 292 SmiCheck smi_check = INLINE_SMI_CHECK); 293 294 #ifdef ENABLE_DEBUGGER_SUPPORT 295 // --------------------------------------------------------------------------- 296 // Debugger Support 297 298 void DebugBreak(); 299 #endif 300 301 // Generates function and stub prologue code. 302 void Prologue(PrologueFrameMode frame_mode); 303 304 // Enter specific kind of exit frame; either in normal or 305 // debug mode. Expects the number of arguments in register rax and 306 // sets up the number of arguments in register rdi and the pointer 307 // to the first argument in register rsi. 308 // 309 // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack 310 // accessible via StackSpaceOperand. 311 void EnterExitFrame(int arg_stack_space = 0, bool save_doubles = false); 312 313 // Enter specific kind of exit frame. Allocates arg_stack_space * kPointerSize 314 // memory (not GCed) on the stack accessible via StackSpaceOperand. 315 void EnterApiExitFrame(int arg_stack_space); 316 317 // Leave the current exit frame. Expects/provides the return value in 318 // register rax:rdx (untouched) and the pointer to the first 319 // argument in register rsi. 320 void LeaveExitFrame(bool save_doubles = false); 321 322 // Leave the current exit frame. Expects/provides the return value in 323 // register rax (untouched). 324 void LeaveApiExitFrame(bool restore_context); 325 326 // Push and pop the registers that can hold pointers. 327 void PushSafepointRegisters() { Pushad(); } 328 void PopSafepointRegisters() { Popad(); } 329 // Store the value in register src in the safepoint register stack 330 // slot for register dst. 331 void StoreToSafepointRegisterSlot(Register dst, const Immediate& imm); 332 void StoreToSafepointRegisterSlot(Register dst, Register src); 333 void LoadFromSafepointRegisterSlot(Register dst, Register src); 334 335 void InitializeRootRegister() { 336 ExternalReference roots_array_start = 337 ExternalReference::roots_array_start(isolate()); 338 Move(kRootRegister, roots_array_start); 339 addq(kRootRegister, Immediate(kRootRegisterBias)); 340 } 341 342 // --------------------------------------------------------------------------- 343 // JavaScript invokes 344 345 // Set up call kind marking in rcx. The method takes rcx as an 346 // explicit first parameter to make the code more readable at the 347 // call sites. 348 void SetCallKind(Register dst, CallKind kind); 349 350 // Invoke the JavaScript function code by either calling or jumping. 351 void InvokeCode(Register code, 352 const ParameterCount& expected, 353 const ParameterCount& actual, 354 InvokeFlag flag, 355 const CallWrapper& call_wrapper, 356 CallKind call_kind); 357 358 void InvokeCode(Handle<Code> code, 359 const ParameterCount& expected, 360 const ParameterCount& actual, 361 RelocInfo::Mode rmode, 362 InvokeFlag flag, 363 const CallWrapper& call_wrapper, 364 CallKind call_kind); 365 366 // Invoke the JavaScript function in the given register. Changes the 367 // current context to the context in the function before invoking. 368 void InvokeFunction(Register function, 369 const ParameterCount& actual, 370 InvokeFlag flag, 371 const CallWrapper& call_wrapper, 372 CallKind call_kind); 373 374 void InvokeFunction(Register function, 375 const ParameterCount& expected, 376 const ParameterCount& actual, 377 InvokeFlag flag, 378 const CallWrapper& call_wrapper, 379 CallKind call_kind); 380 381 void InvokeFunction(Handle<JSFunction> function, 382 const ParameterCount& expected, 383 const ParameterCount& actual, 384 InvokeFlag flag, 385 const CallWrapper& call_wrapper, 386 CallKind call_kind); 387 388 // Invoke specified builtin JavaScript function. Adds an entry to 389 // the unresolved list if the name does not resolve. 390 void InvokeBuiltin(Builtins::JavaScript id, 391 InvokeFlag flag, 392 const CallWrapper& call_wrapper = NullCallWrapper()); 393 394 // Store the function for the given builtin in the target register. 395 void GetBuiltinFunction(Register target, Builtins::JavaScript id); 396 397 // Store the code object for the given builtin in the target register. 398 void GetBuiltinEntry(Register target, Builtins::JavaScript id); 399 400 401 // --------------------------------------------------------------------------- 402 // Smi tagging, untagging and operations on tagged smis. 403 404 // Support for constant splitting. 405 bool IsUnsafeInt(const int32_t x); 406 void SafeMove(Register dst, Smi* src); 407 void SafePush(Smi* src); 408 409 void InitializeSmiConstantRegister() { 410 movq(kSmiConstantRegister, Smi::FromInt(kSmiConstantRegisterValue), 411 RelocInfo::NONE64); 412 } 413 414 // Conversions between tagged smi values and non-tagged integer values. 415 416 // Tag an integer value. The result must be known to be a valid smi value. 417 // Only uses the low 32 bits of the src register. Sets the N and Z flags 418 // based on the value of the resulting smi. 419 void Integer32ToSmi(Register dst, Register src); 420 421 // Stores an integer32 value into a memory field that already holds a smi. 422 void Integer32ToSmiField(const Operand& dst, Register src); 423 424 // Adds constant to src and tags the result as a smi. 425 // Result must be a valid smi. 426 void Integer64PlusConstantToSmi(Register dst, Register src, int constant); 427 428 // Convert smi to 32-bit integer. I.e., not sign extended into 429 // high 32 bits of destination. 430 void SmiToInteger32(Register dst, Register src); 431 void SmiToInteger32(Register dst, const Operand& src); 432 433 // Convert smi to 64-bit integer (sign extended if necessary). 434 void SmiToInteger64(Register dst, Register src); 435 void SmiToInteger64(Register dst, const Operand& src); 436 437 // Multiply a positive smi's integer value by a power of two. 438 // Provides result as 64-bit integer value. 439 void PositiveSmiTimesPowerOfTwoToInteger64(Register dst, 440 Register src, 441 int power); 442 443 // Divide a positive smi's integer value by a power of two. 444 // Provides result as 32-bit integer value. 445 void PositiveSmiDivPowerOfTwoToInteger32(Register dst, 446 Register src, 447 int power); 448 449 // Perform the logical or of two smi values and return a smi value. 450 // If either argument is not a smi, jump to on_not_smis and retain 451 // the original values of source registers. The destination register 452 // may be changed if it's not one of the source registers. 453 void SmiOrIfSmis(Register dst, 454 Register src1, 455 Register src2, 456 Label* on_not_smis, 457 Label::Distance near_jump = Label::kFar); 458 459 460 // Simple comparison of smis. Both sides must be known smis to use these, 461 // otherwise use Cmp. 462 void SmiCompare(Register smi1, Register smi2); 463 void SmiCompare(Register dst, Smi* src); 464 void SmiCompare(Register dst, const Operand& src); 465 void SmiCompare(const Operand& dst, Register src); 466 void SmiCompare(const Operand& dst, Smi* src); 467 // Compare the int32 in src register to the value of the smi stored at dst. 468 void SmiCompareInteger32(const Operand& dst, Register src); 469 // Sets sign and zero flags depending on value of smi in register. 470 void SmiTest(Register src); 471 472 // Functions performing a check on a known or potential smi. Returns 473 // a condition that is satisfied if the check is successful. 474 475 // Is the value a tagged smi. 476 Condition CheckSmi(Register src); 477 Condition CheckSmi(const Operand& src); 478 479 // Is the value a non-negative tagged smi. 480 Condition CheckNonNegativeSmi(Register src); 481 482 // Are both values tagged smis. 483 Condition CheckBothSmi(Register first, Register second); 484 485 // Are both values non-negative tagged smis. 486 Condition CheckBothNonNegativeSmi(Register first, Register second); 487 488 // Are either value a tagged smi. 489 Condition CheckEitherSmi(Register first, 490 Register second, 491 Register scratch = kScratchRegister); 492 493 // Is the value the minimum smi value (since we are using 494 // two's complement numbers, negating the value is known to yield 495 // a non-smi value). 496 Condition CheckIsMinSmi(Register src); 497 498 // Checks whether an 32-bit integer value is a valid for conversion 499 // to a smi. 500 Condition CheckInteger32ValidSmiValue(Register src); 501 502 // Checks whether an 32-bit unsigned integer value is a valid for 503 // conversion to a smi. 504 Condition CheckUInteger32ValidSmiValue(Register src); 505 506 // Check whether src is a Smi, and set dst to zero if it is a smi, 507 // and to one if it isn't. 508 void CheckSmiToIndicator(Register dst, Register src); 509 void CheckSmiToIndicator(Register dst, const Operand& src); 510 511 // Test-and-jump functions. Typically combines a check function 512 // above with a conditional jump. 513 514 // Jump if the value cannot be represented by a smi. 515 void JumpIfNotValidSmiValue(Register src, Label* on_invalid, 516 Label::Distance near_jump = Label::kFar); 517 518 // Jump if the unsigned integer value cannot be represented by a smi. 519 void JumpIfUIntNotValidSmiValue(Register src, Label* on_invalid, 520 Label::Distance near_jump = Label::kFar); 521 522 // Jump to label if the value is a tagged smi. 523 void JumpIfSmi(Register src, 524 Label* on_smi, 525 Label::Distance near_jump = Label::kFar); 526 527 // Jump to label if the value is not a tagged smi. 528 void JumpIfNotSmi(Register src, 529 Label* on_not_smi, 530 Label::Distance near_jump = Label::kFar); 531 532 // Jump to label if the value is not a non-negative tagged smi. 533 void JumpUnlessNonNegativeSmi(Register src, 534 Label* on_not_smi, 535 Label::Distance near_jump = Label::kFar); 536 537 // Jump to label if the value, which must be a tagged smi, has value equal 538 // to the constant. 539 void JumpIfSmiEqualsConstant(Register src, 540 Smi* constant, 541 Label* on_equals, 542 Label::Distance near_jump = Label::kFar); 543 544 // Jump if either or both register are not smi values. 545 void JumpIfNotBothSmi(Register src1, 546 Register src2, 547 Label* on_not_both_smi, 548 Label::Distance near_jump = Label::kFar); 549 550 // Jump if either or both register are not non-negative smi values. 551 void JumpUnlessBothNonNegativeSmi(Register src1, Register src2, 552 Label* on_not_both_smi, 553 Label::Distance near_jump = Label::kFar); 554 555 // Operations on tagged smi values. 556 557 // Smis represent a subset of integers. The subset is always equivalent to 558 // a two's complement interpretation of a fixed number of bits. 559 560 // Add an integer constant to a tagged smi, giving a tagged smi as result. 561 // No overflow testing on the result is done. 562 void SmiAddConstant(Register dst, Register src, Smi* constant); 563 564 // Add an integer constant to a tagged smi, giving a tagged smi as result. 565 // No overflow testing on the result is done. 566 void SmiAddConstant(const Operand& dst, Smi* constant); 567 568 // Add an integer constant to a tagged smi, giving a tagged smi as result, 569 // or jumping to a label if the result cannot be represented by a smi. 570 void SmiAddConstant(Register dst, 571 Register src, 572 Smi* constant, 573 SmiOperationExecutionMode mode, 574 Label* bailout_label, 575 Label::Distance near_jump = Label::kFar); 576 577 // Subtract an integer constant from a tagged smi, giving a tagged smi as 578 // result. No testing on the result is done. Sets the N and Z flags 579 // based on the value of the resulting integer. 580 void SmiSubConstant(Register dst, Register src, Smi* constant); 581 582 // Subtract an integer constant from a tagged smi, giving a tagged smi as 583 // result, or jumping to a label if the result cannot be represented by a smi. 584 void SmiSubConstant(Register dst, 585 Register src, 586 Smi* constant, 587 SmiOperationExecutionMode mode, 588 Label* bailout_label, 589 Label::Distance near_jump = Label::kFar); 590 591 // Negating a smi can give a negative zero or too large positive value. 592 // NOTICE: This operation jumps on success, not failure! 593 void SmiNeg(Register dst, 594 Register src, 595 Label* on_smi_result, 596 Label::Distance near_jump = Label::kFar); 597 598 // Adds smi values and return the result as a smi. 599 // If dst is src1, then src1 will be destroyed if the operation is 600 // successful, otherwise kept intact. 601 void SmiAdd(Register dst, 602 Register src1, 603 Register src2, 604 Label* on_not_smi_result, 605 Label::Distance near_jump = Label::kFar); 606 void SmiAdd(Register dst, 607 Register src1, 608 const Operand& src2, 609 Label* on_not_smi_result, 610 Label::Distance near_jump = Label::kFar); 611 612 void SmiAdd(Register dst, 613 Register src1, 614 Register src2); 615 616 // Subtracts smi values and return the result as a smi. 617 // If dst is src1, then src1 will be destroyed if the operation is 618 // successful, otherwise kept intact. 619 void SmiSub(Register dst, 620 Register src1, 621 Register src2, 622 Label* on_not_smi_result, 623 Label::Distance near_jump = Label::kFar); 624 void SmiSub(Register dst, 625 Register src1, 626 const Operand& src2, 627 Label* on_not_smi_result, 628 Label::Distance near_jump = Label::kFar); 629 630 void SmiSub(Register dst, 631 Register src1, 632 Register src2); 633 634 void SmiSub(Register dst, 635 Register src1, 636 const Operand& src2); 637 638 // Multiplies smi values and return the result as a smi, 639 // if possible. 640 // If dst is src1, then src1 will be destroyed, even if 641 // the operation is unsuccessful. 642 void SmiMul(Register dst, 643 Register src1, 644 Register src2, 645 Label* on_not_smi_result, 646 Label::Distance near_jump = Label::kFar); 647 648 // Divides one smi by another and returns the quotient. 649 // Clobbers rax and rdx registers. 650 void SmiDiv(Register dst, 651 Register src1, 652 Register src2, 653 Label* on_not_smi_result, 654 Label::Distance near_jump = Label::kFar); 655 656 // Divides one smi by another and returns the remainder. 657 // Clobbers rax and rdx registers. 658 void SmiMod(Register dst, 659 Register src1, 660 Register src2, 661 Label* on_not_smi_result, 662 Label::Distance near_jump = Label::kFar); 663 664 // Bitwise operations. 665 void SmiNot(Register dst, Register src); 666 void SmiAnd(Register dst, Register src1, Register src2); 667 void SmiOr(Register dst, Register src1, Register src2); 668 void SmiXor(Register dst, Register src1, Register src2); 669 void SmiAndConstant(Register dst, Register src1, Smi* constant); 670 void SmiOrConstant(Register dst, Register src1, Smi* constant); 671 void SmiXorConstant(Register dst, Register src1, Smi* constant); 672 673 void SmiShiftLeftConstant(Register dst, 674 Register src, 675 int shift_value); 676 void SmiShiftLogicalRightConstant(Register dst, 677 Register src, 678 int shift_value, 679 Label* on_not_smi_result, 680 Label::Distance near_jump = Label::kFar); 681 void SmiShiftArithmeticRightConstant(Register dst, 682 Register src, 683 int shift_value); 684 685 // Shifts a smi value to the left, and returns the result if that is a smi. 686 // Uses and clobbers rcx, so dst may not be rcx. 687 void SmiShiftLeft(Register dst, 688 Register src1, 689 Register src2); 690 // Shifts a smi value to the right, shifting in zero bits at the top, and 691 // returns the unsigned intepretation of the result if that is a smi. 692 // Uses and clobbers rcx, so dst may not be rcx. 693 void SmiShiftLogicalRight(Register dst, 694 Register src1, 695 Register src2, 696 Label* on_not_smi_result, 697 Label::Distance near_jump = Label::kFar); 698 // Shifts a smi value to the right, sign extending the top, and 699 // returns the signed intepretation of the result. That will always 700 // be a valid smi value, since it's numerically smaller than the 701 // original. 702 // Uses and clobbers rcx, so dst may not be rcx. 703 void SmiShiftArithmeticRight(Register dst, 704 Register src1, 705 Register src2); 706 707 // Specialized operations 708 709 // Select the non-smi register of two registers where exactly one is a 710 // smi. If neither are smis, jump to the failure label. 711 void SelectNonSmi(Register dst, 712 Register src1, 713 Register src2, 714 Label* on_not_smis, 715 Label::Distance near_jump = Label::kFar); 716 717 // Converts, if necessary, a smi to a combination of number and 718 // multiplier to be used as a scaled index. 719 // The src register contains a *positive* smi value. The shift is the 720 // power of two to multiply the index value by (e.g. 721 // to index by smi-value * kPointerSize, pass the smi and kPointerSizeLog2). 722 // The returned index register may be either src or dst, depending 723 // on what is most efficient. If src and dst are different registers, 724 // src is always unchanged. 725 SmiIndex SmiToIndex(Register dst, Register src, int shift); 726 727 // Converts a positive smi to a negative index. 728 SmiIndex SmiToNegativeIndex(Register dst, Register src, int shift); 729 730 // Add the value of a smi in memory to an int32 register. 731 // Sets flags as a normal add. 732 void AddSmiField(Register dst, const Operand& src); 733 734 // Basic Smi operations. 735 void Move(Register dst, Smi* source) { 736 LoadSmiConstant(dst, source); 737 } 738 739 void Move(const Operand& dst, Smi* source) { 740 Register constant = GetSmiConstant(source); 741 movq(dst, constant); 742 } 743 744 void Push(Smi* smi); 745 746 // Save away a 64-bit integer on the stack as two 32-bit integers 747 // masquerading as smis so that the garbage collector skips visiting them. 748 void PushInt64AsTwoSmis(Register src, Register scratch = kScratchRegister); 749 // Reconstruct a 64-bit integer from two 32-bit integers masquerading as 750 // smis on the top of stack. 751 void PopInt64AsTwoSmis(Register dst, Register scratch = kScratchRegister); 752 753 void Test(const Operand& dst, Smi* source); 754 755 756 // --------------------------------------------------------------------------- 757 // String macros. 758 759 // Generate code to do a lookup in the number string cache. If the number in 760 // the register object is found in the cache the generated code falls through 761 // with the result in the result register. The object and the result register 762 // can be the same. If the number is not found in the cache the code jumps to 763 // the label not_found with only the content of register object unchanged. 764 void LookupNumberStringCache(Register object, 765 Register result, 766 Register scratch1, 767 Register scratch2, 768 Label* not_found); 769 770 // If object is a string, its map is loaded into object_map. 771 void JumpIfNotString(Register object, 772 Register object_map, 773 Label* not_string, 774 Label::Distance near_jump = Label::kFar); 775 776 777 void JumpIfNotBothSequentialAsciiStrings( 778 Register first_object, 779 Register second_object, 780 Register scratch1, 781 Register scratch2, 782 Label* on_not_both_flat_ascii, 783 Label::Distance near_jump = Label::kFar); 784 785 // Check whether the instance type represents a flat ASCII string. Jump to the 786 // label if not. If the instance type can be scratched specify same register 787 // for both instance type and scratch. 788 void JumpIfInstanceTypeIsNotSequentialAscii( 789 Register instance_type, 790 Register scratch, 791 Label*on_not_flat_ascii_string, 792 Label::Distance near_jump = Label::kFar); 793 794 void JumpIfBothInstanceTypesAreNotSequentialAscii( 795 Register first_object_instance_type, 796 Register second_object_instance_type, 797 Register scratch1, 798 Register scratch2, 799 Label* on_fail, 800 Label::Distance near_jump = Label::kFar); 801 802 void EmitSeqStringSetCharCheck(Register string, 803 Register index, 804 Register value, 805 uint32_t encoding_mask); 806 807 // Checks if the given register or operand is a unique name 808 void JumpIfNotUniqueName(Register reg, Label* not_unique_name, 809 Label::Distance distance = Label::kFar); 810 void JumpIfNotUniqueName(Operand operand, Label* not_unique_name, 811 Label::Distance distance = Label::kFar); 812 813 // --------------------------------------------------------------------------- 814 // Macro instructions. 815 816 // Load/store with specific representation. 817 void Load(Register dst, const Operand& src, Representation r); 818 void Store(const Operand& dst, Register src, Representation r); 819 820 // Load a register with a long value as efficiently as possible. 821 void Set(Register dst, int64_t x); 822 void Set(const Operand& dst, int64_t x); 823 824 // cvtsi2sd instruction only writes to the low 64-bit of dst register, which 825 // hinders register renaming and makes dependence chains longer. So we use 826 // xorps to clear the dst register before cvtsi2sd to solve this issue. 827 void Cvtlsi2sd(XMMRegister dst, Register src); 828 void Cvtlsi2sd(XMMRegister dst, const Operand& src); 829 830 // Move if the registers are not identical. 831 void Move(Register target, Register source); 832 833 // Bit-field support. 834 void TestBit(const Operand& dst, int bit_index); 835 836 // Handle support 837 void Move(Register dst, Handle<Object> source); 838 void Move(const Operand& dst, Handle<Object> source); 839 void Cmp(Register dst, Handle<Object> source); 840 void Cmp(const Operand& dst, Handle<Object> source); 841 void Cmp(Register dst, Smi* src); 842 void Cmp(const Operand& dst, Smi* src); 843 void Push(Handle<Object> source); 844 845 // Load a heap object and handle the case of new-space objects by 846 // indirecting via a global cell. 847 void MoveHeapObject(Register result, Handle<Object> object); 848 849 // Load a global cell into a register. 850 void LoadGlobalCell(Register dst, Handle<Cell> cell); 851 852 // Emit code to discard a non-negative number of pointer-sized elements 853 // from the stack, clobbering only the rsp register. 854 void Drop(int stack_elements); 855 856 void Call(Label* target) { call(target); } 857 void Push(Register src) { push(src); } 858 void Pop(Register dst) { pop(dst); } 859 void PushReturnAddressFrom(Register src) { push(src); } 860 void PopReturnAddressTo(Register dst) { pop(dst); } 861 void MoveDouble(Register dst, const Operand& src) { movq(dst, src); } 862 void MoveDouble(const Operand& dst, Register src) { movq(dst, src); } 863 void Move(Register dst, ExternalReference ext) { 864 movq(dst, reinterpret_cast<Address>(ext.address()), 865 RelocInfo::EXTERNAL_REFERENCE); 866 } 867 868 // Control Flow 869 void Jump(Address destination, RelocInfo::Mode rmode); 870 void Jump(ExternalReference ext); 871 void Jump(Handle<Code> code_object, RelocInfo::Mode rmode); 872 873 void Call(Address destination, RelocInfo::Mode rmode); 874 void Call(ExternalReference ext); 875 void Call(Handle<Code> code_object, 876 RelocInfo::Mode rmode, 877 TypeFeedbackId ast_id = TypeFeedbackId::None()); 878 879 // The size of the code generated for different call instructions. 880 int CallSize(Address destination, RelocInfo::Mode rmode) { 881 return kCallSequenceLength; 882 } 883 int CallSize(ExternalReference ext); 884 int CallSize(Handle<Code> code_object) { 885 // Code calls use 32-bit relative addressing. 886 return kShortCallInstructionLength; 887 } 888 int CallSize(Register target) { 889 // Opcode: REX_opt FF /2 m64 890 return (target.high_bit() != 0) ? 3 : 2; 891 } 892 int CallSize(const Operand& target) { 893 // Opcode: REX_opt FF /2 m64 894 return (target.requires_rex() ? 2 : 1) + target.operand_size(); 895 } 896 897 // Emit call to the code we are currently generating. 898 void CallSelf() { 899 Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location())); 900 Call(self, RelocInfo::CODE_TARGET); 901 } 902 903 // Non-x64 instructions. 904 // Push/pop all general purpose registers. 905 // Does not push rsp/rbp nor any of the assembler's special purpose registers 906 // (kScratchRegister, kSmiConstantRegister, kRootRegister). 907 void Pushad(); 908 void Popad(); 909 // Sets the stack as after performing Popad, without actually loading the 910 // registers. 911 void Dropad(); 912 913 // Compare object type for heap object. 914 // Always use unsigned comparisons: above and below, not less and greater. 915 // Incoming register is heap_object and outgoing register is map. 916 // They may be the same register, and may be kScratchRegister. 917 void CmpObjectType(Register heap_object, InstanceType type, Register map); 918 919 // Compare instance type for map. 920 // Always use unsigned comparisons: above and below, not less and greater. 921 void CmpInstanceType(Register map, InstanceType type); 922 923 // Check if a map for a JSObject indicates that the object has fast elements. 924 // Jump to the specified label if it does not. 925 void CheckFastElements(Register map, 926 Label* fail, 927 Label::Distance distance = Label::kFar); 928 929 // Check if a map for a JSObject indicates that the object can have both smi 930 // and HeapObject elements. Jump to the specified label if it does not. 931 void CheckFastObjectElements(Register map, 932 Label* fail, 933 Label::Distance distance = Label::kFar); 934 935 // Check if a map for a JSObject indicates that the object has fast smi only 936 // elements. Jump to the specified label if it does not. 937 void CheckFastSmiElements(Register map, 938 Label* fail, 939 Label::Distance distance = Label::kFar); 940 941 // Check to see if maybe_number can be stored as a double in 942 // FastDoubleElements. If it can, store it at the index specified by index in 943 // the FastDoubleElements array elements, otherwise jump to fail. Note that 944 // index must not be smi-tagged. 945 void StoreNumberToDoubleElements(Register maybe_number, 946 Register elements, 947 Register index, 948 XMMRegister xmm_scratch, 949 Label* fail, 950 int elements_offset = 0); 951 952 // Compare an object's map with the specified map. 953 void CompareMap(Register obj, Handle<Map> map); 954 955 // Check if the map of an object is equal to a specified map and branch to 956 // label if not. Skip the smi check if not required (object is known to be a 957 // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match 958 // against maps that are ElementsKind transition maps of the specified map. 959 void CheckMap(Register obj, 960 Handle<Map> map, 961 Label* fail, 962 SmiCheckType smi_check_type); 963 964 // Check if the map of an object is equal to a specified map and branch to a 965 // specified target if equal. Skip the smi check if not required (object is 966 // known to be a heap object) 967 void DispatchMap(Register obj, 968 Register unused, 969 Handle<Map> map, 970 Handle<Code> success, 971 SmiCheckType smi_check_type); 972 973 // Check if the object in register heap_object is a string. Afterwards the 974 // register map contains the object map and the register instance_type 975 // contains the instance_type. The registers map and instance_type can be the 976 // same in which case it contains the instance type afterwards. Either of the 977 // registers map and instance_type can be the same as heap_object. 978 Condition IsObjectStringType(Register heap_object, 979 Register map, 980 Register instance_type); 981 982 // Check if the object in register heap_object is a name. Afterwards the 983 // register map contains the object map and the register instance_type 984 // contains the instance_type. The registers map and instance_type can be the 985 // same in which case it contains the instance type afterwards. Either of the 986 // registers map and instance_type can be the same as heap_object. 987 Condition IsObjectNameType(Register heap_object, 988 Register map, 989 Register instance_type); 990 991 // FCmp compares and pops the two values on top of the FPU stack. 992 // The flag results are similar to integer cmp, but requires unsigned 993 // jcc instructions (je, ja, jae, jb, jbe, je, and jz). 994 void FCmp(); 995 996 void ClampUint8(Register reg); 997 998 void ClampDoubleToUint8(XMMRegister input_reg, 999 XMMRegister temp_xmm_reg, 1000 Register result_reg); 1001 1002 void SlowTruncateToI(Register result_reg, Register input_reg, 1003 int offset = HeapNumber::kValueOffset - kHeapObjectTag); 1004 1005 void TruncateHeapNumberToI(Register result_reg, Register input_reg); 1006 void TruncateDoubleToI(Register result_reg, XMMRegister input_reg); 1007 1008 void DoubleToI(Register result_reg, XMMRegister input_reg, 1009 XMMRegister scratch, MinusZeroMode minus_zero_mode, 1010 Label* conversion_failed, Label::Distance dst = Label::kFar); 1011 1012 void TaggedToI(Register result_reg, Register input_reg, XMMRegister temp, 1013 MinusZeroMode minus_zero_mode, Label* lost_precision, 1014 Label::Distance dst = Label::kFar); 1015 1016 void LoadUint32(XMMRegister dst, Register src, XMMRegister scratch); 1017 1018 void LoadInstanceDescriptors(Register map, Register descriptors); 1019 void EnumLength(Register dst, Register map); 1020 void NumberOfOwnDescriptors(Register dst, Register map); 1021 1022 template<typename Field> 1023 void DecodeField(Register reg) { 1024 static const int shift = Field::kShift + kSmiShift; 1025 static const int mask = Field::kMask >> Field::kShift; 1026 shr(reg, Immediate(shift)); 1027 and_(reg, Immediate(mask)); 1028 shl(reg, Immediate(kSmiShift)); 1029 } 1030 1031 // Abort execution if argument is not a number, enabled via --debug-code. 1032 void AssertNumber(Register object); 1033 1034 // Abort execution if argument is a smi, enabled via --debug-code. 1035 void AssertNotSmi(Register object); 1036 1037 // Abort execution if argument is not a smi, enabled via --debug-code. 1038 void AssertSmi(Register object); 1039 void AssertSmi(const Operand& object); 1040 1041 // Abort execution if a 64 bit register containing a 32 bit payload does not 1042 // have zeros in the top 32 bits, enabled via --debug-code. 1043 void AssertZeroExtended(Register reg); 1044 1045 // Abort execution if argument is not a string, enabled via --debug-code. 1046 void AssertString(Register object); 1047 1048 // Abort execution if argument is not a name, enabled via --debug-code. 1049 void AssertName(Register object); 1050 1051 // Abort execution if argument is not the root value with the given index, 1052 // enabled via --debug-code. 1053 void AssertRootValue(Register src, 1054 Heap::RootListIndex root_value_index, 1055 BailoutReason reason); 1056 1057 // --------------------------------------------------------------------------- 1058 // Exception handling 1059 1060 // Push a new try handler and link it into try handler chain. 1061 void PushTryHandler(StackHandler::Kind kind, int handler_index); 1062 1063 // Unlink the stack handler on top of the stack from the try handler chain. 1064 void PopTryHandler(); 1065 1066 // Activate the top handler in the try hander chain and pass the 1067 // thrown value. 1068 void Throw(Register value); 1069 1070 // Propagate an uncatchable exception out of the current JS stack. 1071 void ThrowUncatchable(Register value); 1072 1073 // Throw a message string as an exception. 1074 void Throw(BailoutReason reason); 1075 1076 // Throw a message string as an exception if a condition is not true. 1077 void ThrowIf(Condition cc, BailoutReason reason); 1078 1079 // --------------------------------------------------------------------------- 1080 // Inline caching support 1081 1082 // Generate code for checking access rights - used for security checks 1083 // on access to global objects across environments. The holder register 1084 // is left untouched, but the scratch register and kScratchRegister, 1085 // which must be different, are clobbered. 1086 void CheckAccessGlobalProxy(Register holder_reg, 1087 Register scratch, 1088 Label* miss); 1089 1090 void GetNumberHash(Register r0, Register scratch); 1091 1092 void LoadFromNumberDictionary(Label* miss, 1093 Register elements, 1094 Register key, 1095 Register r0, 1096 Register r1, 1097 Register r2, 1098 Register result); 1099 1100 1101 // --------------------------------------------------------------------------- 1102 // Allocation support 1103 1104 // Allocate an object in new space or old pointer space. If the given space 1105 // is exhausted control continues at the gc_required label. The allocated 1106 // object is returned in result and end of the new object is returned in 1107 // result_end. The register scratch can be passed as no_reg in which case 1108 // an additional object reference will be added to the reloc info. The 1109 // returned pointers in result and result_end have not yet been tagged as 1110 // heap objects. If result_contains_top_on_entry is true the content of 1111 // result is known to be the allocation top on entry (could be result_end 1112 // from a previous call). If result_contains_top_on_entry is true scratch 1113 // should be no_reg as it is never used. 1114 void Allocate(int object_size, 1115 Register result, 1116 Register result_end, 1117 Register scratch, 1118 Label* gc_required, 1119 AllocationFlags flags); 1120 1121 void Allocate(int header_size, 1122 ScaleFactor element_size, 1123 Register element_count, 1124 Register result, 1125 Register result_end, 1126 Register scratch, 1127 Label* gc_required, 1128 AllocationFlags flags); 1129 1130 void Allocate(Register object_size, 1131 Register result, 1132 Register result_end, 1133 Register scratch, 1134 Label* gc_required, 1135 AllocationFlags flags); 1136 1137 // Undo allocation in new space. The object passed and objects allocated after 1138 // it will no longer be allocated. Make sure that no pointers are left to the 1139 // object(s) no longer allocated as they would be invalid when allocation is 1140 // un-done. 1141 void UndoAllocationInNewSpace(Register object); 1142 1143 // Allocate a heap number in new space with undefined value. Returns 1144 // tagged pointer in result register, or jumps to gc_required if new 1145 // space is full. 1146 void AllocateHeapNumber(Register result, 1147 Register scratch, 1148 Label* gc_required); 1149 1150 // Allocate a sequential string. All the header fields of the string object 1151 // are initialized. 1152 void AllocateTwoByteString(Register result, 1153 Register length, 1154 Register scratch1, 1155 Register scratch2, 1156 Register scratch3, 1157 Label* gc_required); 1158 void AllocateAsciiString(Register result, 1159 Register length, 1160 Register scratch1, 1161 Register scratch2, 1162 Register scratch3, 1163 Label* gc_required); 1164 1165 // Allocate a raw cons string object. Only the map field of the result is 1166 // initialized. 1167 void AllocateTwoByteConsString(Register result, 1168 Register scratch1, 1169 Register scratch2, 1170 Label* gc_required); 1171 void AllocateAsciiConsString(Register result, 1172 Register scratch1, 1173 Register scratch2, 1174 Label* gc_required); 1175 1176 // Allocate a raw sliced string object. Only the map field of the result is 1177 // initialized. 1178 void AllocateTwoByteSlicedString(Register result, 1179 Register scratch1, 1180 Register scratch2, 1181 Label* gc_required); 1182 void AllocateAsciiSlicedString(Register result, 1183 Register scratch1, 1184 Register scratch2, 1185 Label* gc_required); 1186 1187 // --------------------------------------------------------------------------- 1188 // Support functions. 1189 1190 // Check if result is zero and op is negative. 1191 void NegativeZeroTest(Register result, Register op, Label* then_label); 1192 1193 // Check if result is zero and op is negative in code using jump targets. 1194 void NegativeZeroTest(CodeGenerator* cgen, 1195 Register result, 1196 Register op, 1197 JumpTarget* then_target); 1198 1199 // Check if result is zero and any of op1 and op2 are negative. 1200 // Register scratch is destroyed, and it must be different from op2. 1201 void NegativeZeroTest(Register result, Register op1, Register op2, 1202 Register scratch, Label* then_label); 1203 1204 // Try to get function prototype of a function and puts the value in 1205 // the result register. Checks that the function really is a 1206 // function and jumps to the miss label if the fast checks fail. The 1207 // function register will be untouched; the other register may be 1208 // clobbered. 1209 void TryGetFunctionPrototype(Register function, 1210 Register result, 1211 Label* miss, 1212 bool miss_on_bound_function = false); 1213 1214 // Generates code for reporting that an illegal operation has 1215 // occurred. 1216 void IllegalOperation(int num_arguments); 1217 1218 // Picks out an array index from the hash field. 1219 // Register use: 1220 // hash - holds the index's hash. Clobbered. 1221 // index - holds the overwritten index on exit. 1222 void IndexFromHash(Register hash, Register index); 1223 1224 // Find the function context up the context chain. 1225 void LoadContext(Register dst, int context_chain_length); 1226 1227 // Conditionally load the cached Array transitioned map of type 1228 // transitioned_kind from the native context if the map in register 1229 // map_in_out is the cached Array map in the native context of 1230 // expected_kind. 1231 void LoadTransitionedArrayMapConditional( 1232 ElementsKind expected_kind, 1233 ElementsKind transitioned_kind, 1234 Register map_in_out, 1235 Register scratch, 1236 Label* no_map_match); 1237 1238 // Load the initial map for new Arrays from a JSFunction. 1239 void LoadInitialArrayMap(Register function_in, 1240 Register scratch, 1241 Register map_out, 1242 bool can_have_holes); 1243 1244 // Load the global function with the given index. 1245 void LoadGlobalFunction(int index, Register function); 1246 void LoadArrayFunction(Register function); 1247 1248 // Load the initial map from the global function. The registers 1249 // function and map can be the same. 1250 void LoadGlobalFunctionInitialMap(Register function, Register map); 1251 1252 // --------------------------------------------------------------------------- 1253 // Runtime calls 1254 1255 // Call a code stub. 1256 void CallStub(CodeStub* stub, TypeFeedbackId ast_id = TypeFeedbackId::None()); 1257 1258 // Tail call a code stub (jump). 1259 void TailCallStub(CodeStub* stub); 1260 1261 // Return from a code stub after popping its arguments. 1262 void StubReturn(int argc); 1263 1264 // Call a runtime routine. 1265 void CallRuntime(const Runtime::Function* f, 1266 int num_arguments, 1267 SaveFPRegsMode save_doubles = kDontSaveFPRegs); 1268 1269 // Call a runtime function and save the value of XMM registers. 1270 void CallRuntimeSaveDoubles(Runtime::FunctionId id) { 1271 const Runtime::Function* function = Runtime::FunctionForId(id); 1272 CallRuntime(function, function->nargs, kSaveFPRegs); 1273 } 1274 1275 // Convenience function: Same as above, but takes the fid instead. 1276 void CallRuntime(Runtime::FunctionId id, 1277 int num_arguments, 1278 SaveFPRegsMode save_doubles = kDontSaveFPRegs) { 1279 CallRuntime(Runtime::FunctionForId(id), num_arguments, save_doubles); 1280 } 1281 1282 // Convenience function: call an external reference. 1283 void CallExternalReference(const ExternalReference& ext, 1284 int num_arguments); 1285 1286 // Tail call of a runtime routine (jump). 1287 // Like JumpToExternalReference, but also takes care of passing the number 1288 // of parameters. 1289 void TailCallExternalReference(const ExternalReference& ext, 1290 int num_arguments, 1291 int result_size); 1292 1293 // Convenience function: tail call a runtime routine (jump). 1294 void TailCallRuntime(Runtime::FunctionId fid, 1295 int num_arguments, 1296 int result_size); 1297 1298 // Jump to a runtime routine. 1299 void JumpToExternalReference(const ExternalReference& ext, int result_size); 1300 1301 // Prepares stack to put arguments (aligns and so on). WIN64 calling 1302 // convention requires to put the pointer to the return value slot into 1303 // rcx (rcx must be preserverd until CallApiFunctionAndReturn). Saves 1304 // context (rsi). Clobbers rax. Allocates arg_stack_space * kPointerSize 1305 // inside the exit frame (not GCed) accessible via StackSpaceOperand. 1306 void PrepareCallApiFunction(int arg_stack_space); 1307 1308 // Calls an API function. Allocates HandleScope, extracts returned value 1309 // from handle and propagates exceptions. Clobbers r14, r15, rbx and 1310 // caller-save registers. Restores context. On return removes 1311 // stack_space * kPointerSize (GCed). 1312 void CallApiFunctionAndReturn(Address function_address, 1313 Address thunk_address, 1314 Register thunk_last_arg, 1315 int stack_space, 1316 Operand return_value_operand, 1317 Operand* context_restore_operand); 1318 1319 // Before calling a C-function from generated code, align arguments on stack. 1320 // After aligning the frame, arguments must be stored in rsp[0], rsp[8], 1321 // etc., not pushed. The argument count assumes all arguments are word sized. 1322 // The number of slots reserved for arguments depends on platform. On Windows 1323 // stack slots are reserved for the arguments passed in registers. On other 1324 // platforms stack slots are only reserved for the arguments actually passed 1325 // on the stack. 1326 void PrepareCallCFunction(int num_arguments); 1327 1328 // Calls a C function and cleans up the space for arguments allocated 1329 // by PrepareCallCFunction. The called function is not allowed to trigger a 1330 // garbage collection, since that might move the code and invalidate the 1331 // return address (unless this is somehow accounted for by the called 1332 // function). 1333 void CallCFunction(ExternalReference function, int num_arguments); 1334 void CallCFunction(Register function, int num_arguments); 1335 1336 // Calculate the number of stack slots to reserve for arguments when calling a 1337 // C function. 1338 int ArgumentStackSlotsForCFunctionCall(int num_arguments); 1339 1340 // --------------------------------------------------------------------------- 1341 // Utilities 1342 1343 void Ret(); 1344 1345 // Return and drop arguments from stack, where the number of arguments 1346 // may be bigger than 2^16 - 1. Requires a scratch register. 1347 void Ret(int bytes_dropped, Register scratch); 1348 1349 Handle<Object> CodeObject() { 1350 ASSERT(!code_object_.is_null()); 1351 return code_object_; 1352 } 1353 1354 // Copy length bytes from source to destination. 1355 // Uses scratch register internally (if you have a low-eight register 1356 // free, do use it, otherwise kScratchRegister will be used). 1357 // The min_length is a minimum limit on the value that length will have. 1358 // The algorithm has some special cases that might be omitted if the string 1359 // is known to always be long. 1360 void CopyBytes(Register destination, 1361 Register source, 1362 Register length, 1363 int min_length = 0, 1364 Register scratch = kScratchRegister); 1365 1366 // Initialize fields with filler values. Fields starting at |start_offset| 1367 // not including end_offset are overwritten with the value in |filler|. At 1368 // the end the loop, |start_offset| takes the value of |end_offset|. 1369 void InitializeFieldsWithFiller(Register start_offset, 1370 Register end_offset, 1371 Register filler); 1372 1373 1374 // --------------------------------------------------------------------------- 1375 // StatsCounter support 1376 1377 void SetCounter(StatsCounter* counter, int value); 1378 void IncrementCounter(StatsCounter* counter, int value); 1379 void DecrementCounter(StatsCounter* counter, int value); 1380 1381 1382 // --------------------------------------------------------------------------- 1383 // Debugging 1384 1385 // Calls Abort(msg) if the condition cc is not satisfied. 1386 // Use --debug_code to enable. 1387 void Assert(Condition cc, BailoutReason reason); 1388 1389 void AssertFastElements(Register elements); 1390 1391 // Like Assert(), but always enabled. 1392 void Check(Condition cc, BailoutReason reason); 1393 1394 // Print a message to stdout and abort execution. 1395 void Abort(BailoutReason msg); 1396 1397 // Check that the stack is aligned. 1398 void CheckStackAlignment(); 1399 1400 // Verify restrictions about code generated in stubs. 1401 void set_generating_stub(bool value) { generating_stub_ = value; } 1402 bool generating_stub() { return generating_stub_; } 1403 void set_has_frame(bool value) { has_frame_ = value; } 1404 bool has_frame() { return has_frame_; } 1405 inline bool AllowThisStubCall(CodeStub* stub); 1406 1407 static int SafepointRegisterStackIndex(Register reg) { 1408 return SafepointRegisterStackIndex(reg.code()); 1409 } 1410 1411 // Activation support. 1412 void EnterFrame(StackFrame::Type type); 1413 void LeaveFrame(StackFrame::Type type); 1414 1415 // Expects object in rax and returns map with validated enum cache 1416 // in rax. Assumes that any other register can be used as a scratch. 1417 void CheckEnumCache(Register null_value, 1418 Label* call_runtime); 1419 1420 // AllocationMemento support. Arrays may have an associated 1421 // AllocationMemento object that can be checked for in order to pretransition 1422 // to another type. 1423 // On entry, receiver_reg should point to the array object. 1424 // scratch_reg gets clobbered. 1425 // If allocation info is present, condition flags are set to equal. 1426 void TestJSArrayForAllocationMemento(Register receiver_reg, 1427 Register scratch_reg, 1428 Label* no_memento_found); 1429 1430 void JumpIfJSArrayHasAllocationMemento(Register receiver_reg, 1431 Register scratch_reg, 1432 Label* memento_found) { 1433 Label no_memento_found; 1434 TestJSArrayForAllocationMemento(receiver_reg, scratch_reg, 1435 &no_memento_found); 1436 j(equal, memento_found); 1437 bind(&no_memento_found); 1438 } 1439 1440 // Jumps to found label if a prototype map has dictionary elements. 1441 void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0, 1442 Register scratch1, Label* found); 1443 1444 private: 1445 // Order general registers are pushed by Pushad. 1446 // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15. 1447 static const int kSafepointPushRegisterIndices[Register::kNumRegisters]; 1448 static const int kNumSafepointSavedRegisters = 11; 1449 static const int kSmiShift = kSmiTagSize + kSmiShiftSize; 1450 1451 bool generating_stub_; 1452 bool has_frame_; 1453 bool root_array_available_; 1454 1455 // Returns a register holding the smi value. The register MUST NOT be 1456 // modified. It may be the "smi 1 constant" register. 1457 Register GetSmiConstant(Smi* value); 1458 1459 intptr_t RootRegisterDelta(ExternalReference other); 1460 1461 // Moves the smi value to the destination register. 1462 void LoadSmiConstant(Register dst, Smi* value); 1463 1464 // This handle will be patched with the code object on installation. 1465 Handle<Object> code_object_; 1466 1467 // Helper functions for generating invokes. 1468 void InvokePrologue(const ParameterCount& expected, 1469 const ParameterCount& actual, 1470 Handle<Code> code_constant, 1471 Register code_register, 1472 Label* done, 1473 bool* definitely_mismatches, 1474 InvokeFlag flag, 1475 Label::Distance near_jump = Label::kFar, 1476 const CallWrapper& call_wrapper = NullCallWrapper(), 1477 CallKind call_kind = CALL_AS_METHOD); 1478 1479 void EnterExitFramePrologue(bool save_rax); 1480 1481 // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack 1482 // accessible via StackSpaceOperand. 1483 void EnterExitFrameEpilogue(int arg_stack_space, bool save_doubles); 1484 1485 void LeaveExitFrameEpilogue(bool restore_context); 1486 1487 // Allocation support helpers. 1488 // Loads the top of new-space into the result register. 1489 // Otherwise the address of the new-space top is loaded into scratch (if 1490 // scratch is valid), and the new-space top is loaded into result. 1491 void LoadAllocationTopHelper(Register result, 1492 Register scratch, 1493 AllocationFlags flags); 1494 1495 // Update allocation top with value in result_end register. 1496 // If scratch is valid, it contains the address of the allocation top. 1497 void UpdateAllocationTopHelper(Register result_end, 1498 Register scratch, 1499 AllocationFlags flags); 1500 1501 // Helper for PopHandleScope. Allowed to perform a GC and returns 1502 // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and 1503 // possibly returns a failure object indicating an allocation failure. 1504 Object* PopHandleScopeHelper(Register saved, 1505 Register scratch, 1506 bool gc_allowed); 1507 1508 // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace. 1509 void InNewSpace(Register object, 1510 Register scratch, 1511 Condition cc, 1512 Label* branch, 1513 Label::Distance distance = Label::kFar); 1514 1515 // Helper for finding the mark bits for an address. Afterwards, the 1516 // bitmap register points at the word with the mark bits and the mask 1517 // the position of the first bit. Uses rcx as scratch and leaves addr_reg 1518 // unchanged. 1519 inline void GetMarkBits(Register addr_reg, 1520 Register bitmap_reg, 1521 Register mask_reg); 1522 1523 // Helper for throwing exceptions. Compute a handler address and jump to 1524 // it. See the implementation for register usage. 1525 void JumpToHandlerEntry(); 1526 1527 // Compute memory operands for safepoint stack slots. 1528 Operand SafepointRegisterSlot(Register reg); 1529 static int SafepointRegisterStackIndex(int reg_code) { 1530 return kNumSafepointRegisters - kSafepointPushRegisterIndices[reg_code] - 1; 1531 } 1532 1533 // Needs access to SafepointRegisterStackIndex for compiled frame 1534 // traversal. 1535 friend class StandardFrame; 1536 }; 1537 1538 1539 // The code patcher is used to patch (typically) small parts of code e.g. for 1540 // debugging and other types of instrumentation. When using the code patcher 1541 // the exact number of bytes specified must be emitted. Is not legal to emit 1542 // relocation information. If any of these constraints are violated it causes 1543 // an assertion. 1544 class CodePatcher { 1545 public: 1546 CodePatcher(byte* address, int size); 1547 virtual ~CodePatcher(); 1548 1549 // Macro assembler to emit code. 1550 MacroAssembler* masm() { return &masm_; } 1551 1552 private: 1553 byte* address_; // The address of the code being patched. 1554 int size_; // Number of bytes of the expected patch size. 1555 MacroAssembler masm_; // Macro assembler used to generate the code. 1556 }; 1557 1558 1559 // ----------------------------------------------------------------------------- 1560 // Static helper functions. 1561 1562 // Generate an Operand for loading a field from an object. 1563 inline Operand FieldOperand(Register object, int offset) { 1564 return Operand(object, offset - kHeapObjectTag); 1565 } 1566 1567 1568 // Generate an Operand for loading an indexed field from an object. 1569 inline Operand FieldOperand(Register object, 1570 Register index, 1571 ScaleFactor scale, 1572 int offset) { 1573 return Operand(object, index, scale, offset - kHeapObjectTag); 1574 } 1575 1576 1577 inline Operand ContextOperand(Register context, int index) { 1578 return Operand(context, Context::SlotOffset(index)); 1579 } 1580 1581 1582 inline Operand GlobalObjectOperand() { 1583 return ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX); 1584 } 1585 1586 1587 // Provides access to exit frame stack space (not GCed). 1588 inline Operand StackSpaceOperand(int index) { 1589 #ifdef _WIN64 1590 const int kShaddowSpace = 4; 1591 return Operand(rsp, (index + kShaddowSpace) * kPointerSize); 1592 #else 1593 return Operand(rsp, index * kPointerSize); 1594 #endif 1595 } 1596 1597 1598 inline Operand StackOperandForReturnAddress(int32_t disp) { 1599 return Operand(rsp, disp); 1600 } 1601 1602 1603 #ifdef GENERATED_CODE_COVERAGE 1604 extern void LogGeneratedCodeCoverage(const char* file_line); 1605 #define CODE_COVERAGE_STRINGIFY(x) #x 1606 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) 1607 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) 1608 #define ACCESS_MASM(masm) { \ 1609 Address x64_coverage_function = FUNCTION_ADDR(LogGeneratedCodeCoverage); \ 1610 masm->pushfq(); \ 1611 masm->Pushad(); \ 1612 masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__))); \ 1613 masm->Call(x64_coverage_function, RelocInfo::EXTERNAL_REFERENCE); \ 1614 masm->pop(rax); \ 1615 masm->Popad(); \ 1616 masm->popfq(); \ 1617 } \ 1618 masm-> 1619 #else 1620 #define ACCESS_MASM(masm) masm-> 1621 #endif 1622 1623 } } // namespace v8::internal 1624 1625 #endif // V8_X64_MACRO_ASSEMBLER_X64_H_ 1626