macro-assembler-x64.h 67 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5 6 7
#ifndef V8_X64_MACRO_ASSEMBLER_X64_H_
#define V8_X64_MACRO_ASSEMBLER_X64_H_

8 9 10
#include "src/assembler.h"
#include "src/frames.h"
#include "src/globals.h"
11

12 13
namespace v8 {
namespace internal {
14

lrn@chromium.org's avatar
lrn@chromium.org committed
15 16 17
// Default scratch register used by MacroAssembler (and other code that needs
// a spare register). The register isn't callee save, and not used by the
// function calling convention.
18 19 20
const Register kScratchRegister = { 10 };      // r10.
const Register kSmiConstantRegister = { 12 };  // r12 (callee save).
const Register kRootRegister = { 13 };         // r13 (callee save).
21
// Value of smi in kSmiConstantRegister.
22
const int kSmiConstantRegisterValue = 1;
23 24
// Actual value of root register is offset from the root array's start
// to take advantage of negitive 8-bit displacement values.
25
const int kRootRegisterBias = 128;
26

27 28 29
// Convenience for platform-independent signatures.
typedef Operand MemOperand;

30 31
enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
32 33 34 35
enum PointersToHereCheck {
  kPointersToHereMaybeInteresting,
  kPointersToHereAreAlwaysInteresting
};
36

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
enum SmiOperationConstraint {
  PRESERVE_SOURCE_REGISTER,
  BAILOUT_ON_NO_OVERFLOW,
  BAILOUT_ON_OVERFLOW,
  NUMBER_OF_CONSTRAINTS
};

STATIC_ASSERT(NUMBER_OF_CONSTRAINTS <= 8);

class SmiOperationExecutionMode : public EnumSet<SmiOperationConstraint, byte> {
 public:
  SmiOperationExecutionMode() : EnumSet<SmiOperationConstraint, byte>(0) { }
  explicit SmiOperationExecutionMode(byte bits)
      : EnumSet<SmiOperationConstraint, byte>(bits) { }
};

53 54 55 56 57 58 59 60 61 62
#ifdef DEBUG
bool AreAliased(Register reg1,
                Register reg2,
                Register reg3 = no_reg,
                Register reg4 = no_reg,
                Register reg5 = no_reg,
                Register reg6 = no_reg,
                Register reg7 = no_reg,
                Register reg8 = no_reg);
#endif
63

64 65 66
// Forward declaration.
class JumpTarget;

67 68 69 70 71 72 73
struct SmiIndex {
  SmiIndex(Register index_register, ScaleFactor scale)
      : reg(index_register),
        scale(scale) {}
  Register reg;
  ScaleFactor scale;
};
74

75

76 77 78
// MacroAssembler implements a collection of frequently used macros.
class MacroAssembler: public Assembler {
 public:
79 80 81 82 83
  // The isolate parameter can be NULL if the macro assembler should
  // not use isolate-dependent functionality. In this case, it's the
  // responsibility of the caller to never invoke such function on the
  // macro assembler.
  MacroAssembler(Isolate* isolate, void* buffer, int size);
84

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
  // Prevent the use of the RootArray during the lifetime of this
  // scope object.
  class NoRootArrayScope BASE_EMBEDDED {
   public:
    explicit NoRootArrayScope(MacroAssembler* assembler)
        : variable_(&assembler->root_array_available_),
          old_value_(assembler->root_array_available_) {
      assembler->root_array_available_ = false;
    }
    ~NoRootArrayScope() {
      *variable_ = old_value_;
    }
   private:
    bool* variable_;
    bool old_value_;
  };

  // Operand pointing to an external reference.
  // May emit code to set up the scratch register. The operand is
  // only guaranteed to be correct as long as the scratch register
  // isn't changed.
  // If the operand is used more than once, use a scratch register
  // that is guaranteed not to be clobbered.
  Operand ExternalOperand(ExternalReference reference,
                          Register scratch = kScratchRegister);
  // Loads and stores the value of an external reference.
  // Special case code for load and store to take advantage of
  // load_rax/store_rax if possible/necessary.
  // For other operations, just use:
  //   Operand operand = ExternalOperand(extref);
  //   operation(operand, ..);
  void Load(Register destination, ExternalReference source);
  void Store(ExternalReference destination, Register source);
  // Loads the address of the external reference into the destination
  // register.
  void LoadAddress(Register destination, ExternalReference source);
  // Returns the size of the code generated by LoadAddress.
  // Used by CallSize(ExternalReference) to find the size of a call.
  int LoadAddressSize(ExternalReference source);
124 125
  // Pushes the address of the external reference onto the stack.
  void PushAddress(ExternalReference source);
126 127

  // Operations on roots in the root-array.
128
  void LoadRoot(Register destination, Heap::RootListIndex index);
129
  void StoreRoot(Register source, Heap::RootListIndex index);
130 131 132 133 134 135
  // Load a root value where the index (or part of it) is variable.
  // The variable_offset register is added to the fixed_offset value
  // to get the index into the root-array.
  void LoadRootIndexed(Register destination,
                       Register variable_offset,
                       int fixed_offset);
136
  void CompareRoot(Register with, Heap::RootListIndex index);
137
  void CompareRoot(const Operand& with, Heap::RootListIndex index);
138 139
  void PushRoot(Heap::RootListIndex index);

140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
  // These functions do not arrange the registers in any particular order so
  // they are not useful for calls that can cause a GC.  The caller can
  // exclude up to 3 registers that do not need to be saved and restored.
  void PushCallerSaved(SaveFPRegsMode fp_mode,
                       Register exclusion1 = no_reg,
                       Register exclusion2 = no_reg,
                       Register exclusion3 = no_reg);
  void PopCallerSaved(SaveFPRegsMode fp_mode,
                      Register exclusion1 = no_reg,
                      Register exclusion2 = no_reg,
                      Register exclusion3 = no_reg);

// ---------------------------------------------------------------------------
// GC Support


  enum RememberedSetFinalAction {
    kReturnAtEnd,
    kFallThroughAtEnd
  };
160

161 162 163
  // Record in the remembered set the fact that we have a pointer to new space
  // at the address pointed to by the addr register.  Only works if addr is not
  // in new space.
164 165
  void RememberedSetHelper(Register object,  // Used for debug code.
                           Register addr,
166 167 168 169 170 171 172 173 174 175 176
                           Register scratch,
                           SaveFPRegsMode save_fp,
                           RememberedSetFinalAction and_then);

  void CheckPageFlag(Register object,
                     Register scratch,
                     int mask,
                     Condition cc,
                     Label* condition_met,
                     Label::Distance condition_met_distance = Label::kFar);

177 178 179 180
  void CheckMapDeprecated(Handle<Map> map,
                          Register scratch,
                          Label* if_deprecated);

181
  // Check if object is in new space.  Jumps if the object is not in new space.
182
  // The register scratch can be object itself, but scratch will be clobbered.
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
  void JumpIfNotInNewSpace(Register object,
                           Register scratch,
                           Label* branch,
                           Label::Distance distance = Label::kFar) {
    InNewSpace(object, scratch, not_equal, branch, distance);
  }

  // Check if object is in new space.  Jumps if the object is in new space.
  // The register scratch can be object itself, but it will be clobbered.
  void JumpIfInNewSpace(Register object,
                        Register scratch,
                        Label* branch,
                        Label::Distance distance = Label::kFar) {
    InNewSpace(object, scratch, equal, branch, distance);
  }

  // Check if an object has the black incremental marking color.  Also uses rcx!
  void JumpIfBlack(Register object,
                   Register scratch0,
                   Register scratch1,
                   Label* on_black,
                   Label::Distance on_black_distance = Label::kFar);

206
  // Detects conservatively whether an object is data-only, i.e. it does need to
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
  // be scanned by the garbage collector.
  void JumpIfDataObject(Register value,
                        Register scratch,
                        Label* not_data_object,
                        Label::Distance not_data_object_distance);

  // Checks the color of an object.  If the object is already grey or black
  // then we just fall through, since it is already live.  If it is white and
  // we can determine that it doesn't need to be scanned, then we just mark it
  // black and fall through.  For the rest we jump to the label so the
  // incremental marker can fix its assumptions.
  void EnsureNotWhite(Register object,
                      Register scratch1,
                      Register scratch2,
                      Label* object_is_white_and_not_data,
                      Label::Distance distance);

  // Notify the garbage collector that we wrote a pointer into an object.
  // |object| is the object being stored into, |value| is the object being
  // stored.  value and scratch registers are clobbered by the operation.
  // The offset is the offset from the start of the object, not the offset from
  // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
  void RecordWriteField(
      Register object,
      int offset,
      Register value,
      Register scratch,
      SaveFPRegsMode save_fp,
      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
236 237 238
      SmiCheck smi_check = INLINE_SMI_CHECK,
      PointersToHereCheck pointers_to_here_check_for_value =
          kPointersToHereMaybeInteresting);
239 240 241 242 243 244 245 246 247 248

  // As above, but the offset has the tag presubtracted.  For use with
  // Operand(reg, off).
  void RecordWriteContextSlot(
      Register context,
      int offset,
      Register value,
      Register scratch,
      SaveFPRegsMode save_fp,
      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
249 250 251
      SmiCheck smi_check = INLINE_SMI_CHECK,
      PointersToHereCheck pointers_to_here_check_for_value =
          kPointersToHereMaybeInteresting) {
252 253 254 255 256 257
    RecordWriteField(context,
                     offset + kHeapObjectTag,
                     value,
                     scratch,
                     save_fp,
                     remembered_set_action,
258 259
                     smi_check,
                     pointers_to_here_check_for_value);
260 261 262 263
  }

  // Notify the garbage collector that we wrote a pointer into a fixed array.
  // |array| is the array being stored into, |value| is the
264 265
  // object being stored.  |index| is the array index represented as a non-smi.
  // All registers are clobbered by the operation RecordWriteArray
266 267 268 269 270 271 272 273
  // filters out smis so it does not update the write barrier if the
  // value is a smi.
  void RecordWriteArray(
      Register array,
      Register value,
      Register index,
      SaveFPRegsMode save_fp,
      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
274 275 276 277 278 279 280 281 282
      SmiCheck smi_check = INLINE_SMI_CHECK,
      PointersToHereCheck pointers_to_here_check_for_value =
          kPointersToHereMaybeInteresting);

  void RecordWriteForMap(
      Register object,
      Register map,
      Register dst,
      SaveFPRegsMode save_fp);
283

284
  // For page containing |object| mark region covering |address|
285
  // dirty. |object| is the object being stored into, |value| is the
286
  // object being stored. The address and value registers are clobbered by the
287 288
  // operation.  RecordWrite filters out smis so it does not update
  // the write barrier if the value is a smi.
289 290 291 292 293 294
  void RecordWrite(
      Register object,
      Register address,
      Register value,
      SaveFPRegsMode save_fp,
      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
295 296 297
      SmiCheck smi_check = INLINE_SMI_CHECK,
      PointersToHereCheck pointers_to_here_check_for_value =
          kPointersToHereMaybeInteresting);
298

299 300 301
  // ---------------------------------------------------------------------------
  // Debugger Support

serya@chromium.org's avatar
serya@chromium.org committed
302
  void DebugBreak();
303

304
  // Generates function and stub prologue code.
305 306
  void StubPrologue();
  void Prologue(bool code_pre_aging);
307

308 309
  // Enter specific kind of exit frame; either in normal or
  // debug mode. Expects the number of arguments in register rax and
310 311
  // sets up the number of arguments in register rdi and the pointer
  // to the first argument in register rsi.
312 313 314
  //
  // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack
  // accessible via StackSpaceOperand.
315
  void EnterExitFrame(int arg_stack_space = 0, bool save_doubles = false);
316

317 318 319
  // Enter specific kind of exit frame. Allocates arg_stack_space * kPointerSize
  // memory (not GCed) on the stack accessible via StackSpaceOperand.
  void EnterApiExitFrame(int arg_stack_space);
320

321 322 323
  // Leave the current exit frame. Expects/provides the return value in
  // register rax:rdx (untouched) and the pointer to the first
  // argument in register rsi.
324
  void LeaveExitFrame(bool save_doubles = false);
325

326 327
  // Leave the current exit frame. Expects/provides the return value in
  // register rax (untouched).
328
  void LeaveApiExitFrame(bool restore_context);
329

330
  // Push and pop the registers that can hold pointers.
331 332
  void PushSafepointRegisters() { Pushad(); }
  void PopSafepointRegisters() { Popad(); }
333 334
  // Store the value in register src in the safepoint register stack
  // slot for register dst.
335
  void StoreToSafepointRegisterSlot(Register dst, const Immediate& imm);
336
  void StoreToSafepointRegisterSlot(Register dst, Register src);
337
  void LoadFromSafepointRegisterSlot(Register dst, Register src);
338

339
  void InitializeRootRegister() {
340 341
    ExternalReference roots_array_start =
        ExternalReference::roots_array_start(isolate());
342
    Move(kRootRegister, roots_array_start);
343
    addp(kRootRegister, Immediate(kRootRegisterBias));
344 345
  }

346 347 348 349
  // ---------------------------------------------------------------------------
  // JavaScript invokes

  // Invoke the JavaScript function code by either calling or jumping.
350
  void InvokeCode(Register code,
351 352
                  const ParameterCount& expected,
                  const ParameterCount& actual,
353
                  InvokeFlag flag,
354
                  const CallWrapper& call_wrapper);
355 356 357 358 359

  // Invoke the JavaScript function in the given register. Changes the
  // current context to the context in the function before invoking.
  void InvokeFunction(Register function,
                      const ParameterCount& actual,
360
                      InvokeFlag flag,
361
                      const CallWrapper& call_wrapper);
362

363 364 365 366
  void InvokeFunction(Register function,
                      const ParameterCount& expected,
                      const ParameterCount& actual,
                      InvokeFlag flag,
367
                      const CallWrapper& call_wrapper);
368

369
  void InvokeFunction(Handle<JSFunction> function,
370
                      const ParameterCount& expected,
371
                      const ParameterCount& actual,
372
                      InvokeFlag flag,
373
                      const CallWrapper& call_wrapper);
374

375 376
  // Invoke specified builtin JavaScript function. Adds an entry to
  // the unresolved list if the name does not resolve.
377 378
  void InvokeBuiltin(Builtins::JavaScript id,
                     InvokeFlag flag,
379
                     const CallWrapper& call_wrapper = NullCallWrapper());
380

381 382 383
  // Store the function for the given builtin in the target register.
  void GetBuiltinFunction(Register target, Builtins::JavaScript id);

384 385 386
  // Store the code object for the given builtin in the target register.
  void GetBuiltinEntry(Register target, Builtins::JavaScript id);

387 388 389 390

  // ---------------------------------------------------------------------------
  // Smi tagging, untagging and operations on tagged smis.

391 392 393 394 395
  // Support for constant splitting.
  bool IsUnsafeInt(const int32_t x);
  void SafeMove(Register dst, Smi* src);
  void SafePush(Smi* src);

396
  void InitializeSmiConstantRegister() {
397
    Move(kSmiConstantRegister, Smi::FromInt(kSmiConstantRegisterValue),
398
         Assembler::RelocInfoNone());
399 400
  }

401 402 403
  // Conversions between tagged smi values and non-tagged integer values.

  // Tag an integer value. The result must be known to be a valid smi value.
404
  // Only uses the low 32 bits of the src register. Sets the N and Z flags
405
  // based on the value of the resulting smi.
406 407
  void Integer32ToSmi(Register dst, Register src);

408 409 410
  // Stores an integer32 value into a memory field that already holds a smi.
  void Integer32ToSmiField(const Operand& dst, Register src);

411 412
  // Adds constant to src and tags the result as a smi.
  // Result must be a valid smi.
413
  void Integer64PlusConstantToSmi(Register dst, Register src, int constant);
414 415 416 417

  // Convert smi to 32-bit integer. I.e., not sign extended into
  // high 32 bits of destination.
  void SmiToInteger32(Register dst, Register src);
418
  void SmiToInteger32(Register dst, const Operand& src);
419 420 421

  // Convert smi to 64-bit integer (sign extended if necessary).
  void SmiToInteger64(Register dst, Register src);
422
  void SmiToInteger64(Register dst, const Operand& src);
423 424 425 426 427 428 429

  // Multiply a positive smi's integer value by a power of two.
  // Provides result as 64-bit integer value.
  void PositiveSmiTimesPowerOfTwoToInteger64(Register dst,
                                             Register src,
                                             int power);

430 431 432 433 434 435
  // Divide a positive smi's integer value by a power of two.
  // Provides result as 32-bit integer value.
  void PositiveSmiDivPowerOfTwoToInteger32(Register dst,
                                           Register src,
                                           int power);

436 437 438 439 440 441 442
  // Perform the logical or of two smi values and return a smi value.
  // If either argument is not a smi, jump to on_not_smis and retain
  // the original values of source registers. The destination register
  // may be changed if it's not one of the source registers.
  void SmiOrIfSmis(Register dst,
                   Register src1,
                   Register src2,
443 444
                   Label* on_not_smis,
                   Label::Distance near_jump = Label::kFar);
445

446

447 448 449
  // Simple comparison of smis.  Both sides must be known smis to use these,
  // otherwise use Cmp.
  void SmiCompare(Register smi1, Register smi2);
450
  void SmiCompare(Register dst, Smi* src);
451
  void SmiCompare(Register dst, const Operand& src);
452 453
  void SmiCompare(const Operand& dst, Register src);
  void SmiCompare(const Operand& dst, Smi* src);
454 455
  // Compare the int32 in src register to the value of the smi stored at dst.
  void SmiCompareInteger32(const Operand& dst, Register src);
456 457 458
  // Sets sign and zero flags depending on value of smi in register.
  void SmiTest(Register src);

459 460 461 462 463
  // Functions performing a check on a known or potential smi. Returns
  // a condition that is satisfied if the check is successful.

  // Is the value a tagged smi.
  Condition CheckSmi(Register src);
464
  Condition CheckSmi(const Operand& src);
465

466 467
  // Is the value a non-negative tagged smi.
  Condition CheckNonNegativeSmi(Register src);
468

469
  // Are both values tagged smis.
470 471
  Condition CheckBothSmi(Register first, Register second);

472 473
  // Are both values non-negative tagged smis.
  Condition CheckBothNonNegativeSmi(Register first, Register second);
474

475
  // Are either value a tagged smi.
476 477 478
  Condition CheckEitherSmi(Register first,
                           Register second,
                           Register scratch = kScratchRegister);
479

480 481 482 483 484 485 486 487 488
  // Is the value the minimum smi value (since we are using
  // two's complement numbers, negating the value is known to yield
  // a non-smi value).
  Condition CheckIsMinSmi(Register src);

  // Checks whether an 32-bit integer value is a valid for conversion
  // to a smi.
  Condition CheckInteger32ValidSmiValue(Register src);

489 490 491 492
  // Checks whether an 32-bit unsigned integer value is a valid for
  // conversion to a smi.
  Condition CheckUInteger32ValidSmiValue(Register src);

493 494 495 496 497
  // Check whether src is a Smi, and set dst to zero if it is a smi,
  // and to one if it isn't.
  void CheckSmiToIndicator(Register dst, Register src);
  void CheckSmiToIndicator(Register dst, const Operand& src);

498 499 500
  // Test-and-jump functions. Typically combines a check function
  // above with a conditional jump.

501 502 503 504
  // Jump if the value can be represented by a smi.
  void JumpIfValidSmiValue(Register src, Label* on_valid,
                           Label::Distance near_jump = Label::kFar);

505
  // Jump if the value cannot be represented by a smi.
506 507
  void JumpIfNotValidSmiValue(Register src, Label* on_invalid,
                              Label::Distance near_jump = Label::kFar);
508

509 510 511 512
  // Jump if the unsigned integer value can be represented by a smi.
  void JumpIfUIntValidSmiValue(Register src, Label* on_valid,
                               Label::Distance near_jump = Label::kFar);

513
  // Jump if the unsigned integer value cannot be represented by a smi.
514 515
  void JumpIfUIntNotValidSmiValue(Register src, Label* on_invalid,
                                  Label::Distance near_jump = Label::kFar);
516

517
  // Jump to label if the value is a tagged smi.
518 519 520
  void JumpIfSmi(Register src,
                 Label* on_smi,
                 Label::Distance near_jump = Label::kFar);
521 522

  // Jump to label if the value is not a tagged smi.
523 524 525
  void JumpIfNotSmi(Register src,
                    Label* on_not_smi,
                    Label::Distance near_jump = Label::kFar);
526

527
  // Jump to label if the value is not a non-negative tagged smi.
528 529 530
  void JumpUnlessNonNegativeSmi(Register src,
                                Label* on_not_smi,
                                Label::Distance near_jump = Label::kFar);
531

532
  // Jump to label if the value, which must be a tagged smi, has value equal
533
  // to the constant.
534 535
  void JumpIfSmiEqualsConstant(Register src,
                               Smi* constant,
536 537
                               Label* on_equals,
                               Label::Distance near_jump = Label::kFar);
538

539
  // Jump if either or both register are not smi values.
540 541
  void JumpIfNotBothSmi(Register src1,
                        Register src2,
542 543
                        Label* on_not_both_smi,
                        Label::Distance near_jump = Label::kFar);
544

545 546
  // Jump if either or both register are not non-negative smi values.
  void JumpUnlessBothNonNegativeSmi(Register src1, Register src2,
547 548
                                    Label* on_not_both_smi,
                                    Label::Distance near_jump = Label::kFar);
549

550 551 552 553 554
  // Operations on tagged smi values.

  // Smis represent a subset of integers. The subset is always equivalent to
  // a two's complement interpretation of a fixed number of bits.

555 556 557 558
  // Add an integer constant to a tagged smi, giving a tagged smi as result.
  // No overflow testing on the result is done.
  void SmiAddConstant(Register dst, Register src, Smi* constant);

559 560 561 562
  // Add an integer constant to a tagged smi, giving a tagged smi as result.
  // No overflow testing on the result is done.
  void SmiAddConstant(const Operand& dst, Smi* constant);

563 564 565 566
  // Add an integer constant to a tagged smi, giving a tagged smi as result,
  // or jumping to a label if the result cannot be represented by a smi.
  void SmiAddConstant(Register dst,
                      Register src,
567
                      Smi* constant,
568 569
                      SmiOperationExecutionMode mode,
                      Label* bailout_label,
570
                      Label::Distance near_jump = Label::kFar);
571

572
  // Subtract an integer constant from a tagged smi, giving a tagged smi as
573 574
  // result. No testing on the result is done. Sets the N and Z flags
  // based on the value of the resulting integer.
575 576
  void SmiSubConstant(Register dst, Register src, Smi* constant);

577 578 579 580
  // Subtract an integer constant from a tagged smi, giving a tagged smi as
  // result, or jumping to a label if the result cannot be represented by a smi.
  void SmiSubConstant(Register dst,
                      Register src,
581
                      Smi* constant,
582 583
                      SmiOperationExecutionMode mode,
                      Label* bailout_label,
584
                      Label::Distance near_jump = Label::kFar);
585

586
  // Negating a smi can give a negative zero or too large positive value.
587
  // NOTICE: This operation jumps on success, not failure!
588 589
  void SmiNeg(Register dst,
              Register src,
590 591
              Label* on_smi_result,
              Label::Distance near_jump = Label::kFar);
592 593

  // Adds smi values and return the result as a smi.
594 595
  // If dst is src1, then src1 will be destroyed if the operation is
  // successful, otherwise kept intact.
596 597 598
  void SmiAdd(Register dst,
              Register src1,
              Register src2,
599 600
              Label* on_not_smi_result,
              Label::Distance near_jump = Label::kFar);
601 602 603
  void SmiAdd(Register dst,
              Register src1,
              const Operand& src2,
604 605
              Label* on_not_smi_result,
              Label::Distance near_jump = Label::kFar);
606 607 608 609

  void SmiAdd(Register dst,
              Register src1,
              Register src2);
610

611
  // Subtracts smi values and return the result as a smi.
612 613
  // If dst is src1, then src1 will be destroyed if the operation is
  // successful, otherwise kept intact.
614 615 616
  void SmiSub(Register dst,
              Register src1,
              Register src2,
617 618
              Label* on_not_smi_result,
              Label::Distance near_jump = Label::kFar);
619 620
  void SmiSub(Register dst,
              Register src1,
621
              const Operand& src2,
622 623
              Label* on_not_smi_result,
              Label::Distance near_jump = Label::kFar);
624

625 626 627 628
  void SmiSub(Register dst,
              Register src1,
              Register src2);

629 630 631
  void SmiSub(Register dst,
              Register src1,
              const Operand& src2);
632

633 634 635 636 637 638 639
  // Multiplies smi values and return the result as a smi,
  // if possible.
  // If dst is src1, then src1 will be destroyed, even if
  // the operation is unsuccessful.
  void SmiMul(Register dst,
              Register src1,
              Register src2,
640 641
              Label* on_not_smi_result,
              Label::Distance near_jump = Label::kFar);
642 643 644 645 646 647

  // Divides one smi by another and returns the quotient.
  // Clobbers rax and rdx registers.
  void SmiDiv(Register dst,
              Register src1,
              Register src2,
648 649
              Label* on_not_smi_result,
              Label::Distance near_jump = Label::kFar);
650 651 652 653 654 655

  // Divides one smi by another and returns the remainder.
  // Clobbers rax and rdx registers.
  void SmiMod(Register dst,
              Register src1,
              Register src2,
656 657
              Label* on_not_smi_result,
              Label::Distance near_jump = Label::kFar);
658 659 660 661 662 663

  // Bitwise operations.
  void SmiNot(Register dst, Register src);
  void SmiAnd(Register dst, Register src1, Register src2);
  void SmiOr(Register dst, Register src1, Register src2);
  void SmiXor(Register dst, Register src1, Register src2);
664 665 666
  void SmiAndConstant(Register dst, Register src1, Smi* constant);
  void SmiOrConstant(Register dst, Register src1, Smi* constant);
  void SmiXorConstant(Register dst, Register src1, Smi* constant);
667 668 669

  void SmiShiftLeftConstant(Register dst,
                            Register src,
670 671 672
                            int shift_value,
                            Label* on_not_smi_result = NULL,
                            Label::Distance near_jump = Label::kFar);
673
  void SmiShiftLogicalRightConstant(Register dst,
674 675 676 677
                                    Register src,
                                    int shift_value,
                                    Label* on_not_smi_result,
                                    Label::Distance near_jump = Label::kFar);
678 679 680 681 682 683 684 685
  void SmiShiftArithmeticRightConstant(Register dst,
                                       Register src,
                                       int shift_value);

  // Shifts a smi value to the left, and returns the result if that is a smi.
  // Uses and clobbers rcx, so dst may not be rcx.
  void SmiShiftLeft(Register dst,
                    Register src1,
686 687 688
                    Register src2,
                    Label* on_not_smi_result = NULL,
                    Label::Distance near_jump = Label::kFar);
689 690 691 692
  // Shifts a smi value to the right, shifting in zero bits at the top, and
  // returns the unsigned intepretation of the result if that is a smi.
  // Uses and clobbers rcx, so dst may not be rcx.
  void SmiShiftLogicalRight(Register dst,
693 694
                            Register src1,
                            Register src2,
695 696
                            Label* on_not_smi_result,
                            Label::Distance near_jump = Label::kFar);
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
  // Shifts a smi value to the right, sign extending the top, and
  // returns the signed intepretation of the result. That will always
  // be a valid smi value, since it's numerically smaller than the
  // original.
  // Uses and clobbers rcx, so dst may not be rcx.
  void SmiShiftArithmeticRight(Register dst,
                               Register src1,
                               Register src2);

  // Specialized operations

  // Select the non-smi register of two registers where exactly one is a
  // smi. If neither are smis, jump to the failure label.
  void SelectNonSmi(Register dst,
                    Register src1,
                    Register src2,
713 714
                    Label* on_not_smis,
                    Label::Distance near_jump = Label::kFar);
715

716 717 718 719 720 721 722 723 724 725 726 727 728
  // Converts, if necessary, a smi to a combination of number and
  // multiplier to be used as a scaled index.
  // The src register contains a *positive* smi value. The shift is the
  // power of two to multiply the index value by (e.g.
  // to index by smi-value * kPointerSize, pass the smi and kPointerSizeLog2).
  // The returned index register may be either src or dst, depending
  // on what is most efficient. If src and dst are different registers,
  // src is always unchanged.
  SmiIndex SmiToIndex(Register dst, Register src, int shift);

  // Converts a positive smi to a negative index.
  SmiIndex SmiToNegativeIndex(Register dst, Register src, int shift);

729 730 731 732
  // Add the value of a smi in memory to an int32 register.
  // Sets flags as a normal add.
  void AddSmiField(Register dst, const Operand& src);

733
  // Basic Smi operations.
734
  void Move(Register dst, Smi* source) {
735
    LoadSmiConstant(dst, source);
736 737 738
  }

  void Move(const Operand& dst, Smi* source) {
739
    Register constant = GetSmiConstant(source);
740
    movp(dst, constant);
741 742
  }

743
  void Push(Smi* smi);
744

745
  // Save away a raw integer with pointer size on the stack as two integers
746
  // masquerading as smis so that the garbage collector skips visiting them.
747 748 749 750
  void PushRegisterAsTwoSmis(Register src, Register scratch = kScratchRegister);
  // Reconstruct a raw integer with pointer size from two integers masquerading
  // as smis on the top of stack.
  void PopRegisterAsTwoSmis(Register dst, Register scratch = kScratchRegister);
751

752 753
  void Test(const Operand& dst, Smi* source);

754

755 756
  // ---------------------------------------------------------------------------
  // String macros.
757

758 759 760 761 762 763 764 765 766 767 768
  // Generate code to do a lookup in the number string cache. If the number in
  // the register object is found in the cache the generated code falls through
  // with the result in the result register. The object and the result register
  // can be the same. If the number is not found in the cache the code jumps to
  // the label not_found with only the content of register object unchanged.
  void LookupNumberStringCache(Register object,
                               Register result,
                               Register scratch1,
                               Register scratch2,
                               Label* not_found);

769 770 771
  // If object is a string, its map is loaded into object_map.
  void JumpIfNotString(Register object,
                       Register object_map,
772 773
                       Label* not_string,
                       Label::Distance near_jump = Label::kFar);
774 775


776 777 778 779 780 781 782
  void JumpIfNotBothSequentialAsciiStrings(
      Register first_object,
      Register second_object,
      Register scratch1,
      Register scratch2,
      Label* on_not_both_flat_ascii,
      Label::Distance near_jump = Label::kFar);
783

784
  // Check whether the instance type represents a flat ASCII string. Jump to the
785 786
  // label if not. If the instance type can be scratched specify same register
  // for both instance type and scratch.
787 788 789
  void JumpIfInstanceTypeIsNotSequentialAscii(
      Register instance_type,
      Register scratch,
790 791
      Label*on_not_flat_ascii_string,
      Label::Distance near_jump = Label::kFar);
792 793 794 795 796 797

  void JumpIfBothInstanceTypesAreNotSequentialAscii(
      Register first_object_instance_type,
      Register second_object_instance_type,
      Register scratch1,
      Register scratch2,
798 799
      Label* on_fail,
      Label::Distance near_jump = Label::kFar);
800

801 802 803 804 805
  void EmitSeqStringSetCharCheck(Register string,
                                 Register index,
                                 Register value,
                                 uint32_t encoding_mask);

806 807 808 809 810 811
  // Checks if the given register or operand is a unique name
  void JumpIfNotUniqueName(Register reg, Label* not_unique_name,
                           Label::Distance distance = Label::kFar);
  void JumpIfNotUniqueName(Operand operand, Label* not_unique_name,
                           Label::Distance distance = Label::kFar);

812
  // ---------------------------------------------------------------------------
813
  // Macro instructions.
814

815 816 817 818
  // Load/store with specific representation.
  void Load(Register dst, const Operand& src, Representation r);
  void Store(const Operand& dst, Register src, Representation r);

819
  // Load a register with a long value as efficiently as possible.
820
  void Set(Register dst, int64_t x);
821
  void Set(const Operand& dst, intptr_t x);
822

823 824 825 826 827 828
  // cvtsi2sd instruction only writes to the low 64-bit of dst register, which
  // hinders register renaming and makes dependence chains longer. So we use
  // xorps to clear the dst register before cvtsi2sd to solve this issue.
  void Cvtlsi2sd(XMMRegister dst, Register src);
  void Cvtlsi2sd(XMMRegister dst, const Operand& src);

829 830 831
  // Move if the registers are not identical.
  void Move(Register target, Register source);

832 833 834 835 836 837 838
  // TestBit and Load SharedFunctionInfo special field.
  void TestBitSharedFunctionInfoSpecialField(Register base,
                                             int offset,
                                             int bit_index);
  void LoadSharedFunctionInfoSpecialField(Register dst,
                                          Register base,
                                          int offset);
839

840 841 842 843
  // Handle support
  void Move(Register dst, Handle<Object> source);
  void Move(const Operand& dst, Handle<Object> source);
  void Cmp(Register dst, Handle<Object> source);
844
  void Cmp(const Operand& dst, Handle<Object> source);
845 846
  void Cmp(Register dst, Smi* src);
  void Cmp(const Operand& dst, Smi* src);
847
  void Push(Handle<Object> source);
848

849 850
  // Load a heap object and handle the case of new-space objects by
  // indirecting via a global cell.
851
  void MoveHeapObject(Register result, Handle<Object> object);
852

853
  // Load a global cell into a register.
854
  void LoadGlobalCell(Register dst, Handle<Cell> cell);
855

856 857
  // Emit code to discard a non-negative number of pointer-sized elements
  // from the stack, clobbering only the rsp register.
858
  void Drop(int stack_elements);
859 860 861 862 863
  // Emit code to discard a positive number of pointer-sized elements
  // from the stack under the return address which remains on the top,
  // clobbering the rsp register.
  void DropUnderReturnAddress(int stack_elements,
                              Register scratch = kScratchRegister);
864

865
  void Call(Label* target) { call(target); }
866 867
  void Push(Register src);
  void Push(const Operand& src);
868
  void PushQuad(const Operand& src);
869 870 871 872
  void Push(Immediate value);
  void PushImm32(int32_t imm32);
  void Pop(Register dst);
  void Pop(const Operand& dst);
873
  void PopQuad(const Operand& dst);
874 875
  void PushReturnAddressFrom(Register src) { pushq(src); }
  void PopReturnAddressTo(Register dst) { popq(dst); }
876
  void Move(Register dst, ExternalReference ext) {
877
    movp(dst, reinterpret_cast<void*>(ext.address()),
878 879
         RelocInfo::EXTERNAL_REFERENCE);
  }
880

881 882 883 884
  // Loads a pointer into a register with a relocation mode.
  void Move(Register dst, void* ptr, RelocInfo::Mode rmode) {
    // This method must not be used with heap object references. The stored
    // address is not GC safe. Use the handle version instead.
885
    DCHECK(rmode > RelocInfo::LAST_GCED_ENUM);
886 887 888 889 890
    movp(dst, ptr, rmode);
  }

  void Move(Register dst, Handle<Object> value, RelocInfo::Mode rmode) {
    AllowDeferredHandleDereference using_raw_address;
891 892 893
    DCHECK(!RelocInfo::IsNone(rmode));
    DCHECK(value->IsHeapObject());
    DCHECK(!isolate()->heap()->InNewSpace(*value));
894
    movp(dst, reinterpret_cast<void*>(value.location()), rmode);
895 896
  }

897 898 899
  // Control Flow
  void Jump(Address destination, RelocInfo::Mode rmode);
  void Jump(ExternalReference ext);
900
  void Jump(const Operand& op);
901 902
  void Jump(Handle<Code> code_object, RelocInfo::Mode rmode);

903 904
  void Call(Address destination, RelocInfo::Mode rmode);
  void Call(ExternalReference ext);
905
  void Call(const Operand& op);
906 907
  void Call(Handle<Code> code_object,
            RelocInfo::Mode rmode,
908
            TypeFeedbackId ast_id = TypeFeedbackId::None());
909

lrn@chromium.org's avatar
lrn@chromium.org committed
910
  // The size of the code generated for different call instructions.
911
  int CallSize(Address destination) {
912
    return kCallSequenceLength;
lrn@chromium.org's avatar
lrn@chromium.org committed
913
  }
914
  int CallSize(ExternalReference ext);
lrn@chromium.org's avatar
lrn@chromium.org committed
915 916 917 918 919 920 921 922 923 924 925 926 927
  int CallSize(Handle<Code> code_object) {
    // Code calls use 32-bit relative addressing.
    return kShortCallInstructionLength;
  }
  int CallSize(Register target) {
    // Opcode: REX_opt FF /2 m64
    return (target.high_bit() != 0) ? 3 : 2;
  }
  int CallSize(const Operand& target) {
    // Opcode: REX_opt FF /2 m64
    return (target.requires_rex() ? 2 : 1) + target.operand_size();
  }

928 929 930
  // Emit call to the code we are currently generating.
  void CallSelf() {
    Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
931
    Call(self, RelocInfo::CODE_TARGET);
932 933
  }

934 935 936 937 938 939
  // Non-x64 instructions.
  // Push/pop all general purpose registers.
  // Does not push rsp/rbp nor any of the assembler's special purpose registers
  // (kScratchRegister, kSmiConstantRegister, kRootRegister).
  void Pushad();
  void Popad();
940 941 942
  // Sets the stack as after performing Popad, without actually loading the
  // registers.
  void Dropad();
943

944
  // Compare object type for heap object.
945
  // Always use unsigned comparisons: above and below, not less and greater.
946
  // Incoming register is heap_object and outgoing register is map.
947
  // They may be the same register, and may be kScratchRegister.
948 949 950
  void CmpObjectType(Register heap_object, InstanceType type, Register map);

  // Compare instance type for map.
951
  // Always use unsigned comparisons: above and below, not less and greater.
952 953
  void CmpInstanceType(Register map, InstanceType type);

954 955 956 957 958 959
  // Check if a map for a JSObject indicates that the object has fast elements.
  // Jump to the specified label if it does not.
  void CheckFastElements(Register map,
                         Label* fail,
                         Label::Distance distance = Label::kFar);

960 961 962 963 964 965 966 967
  // Check if a map for a JSObject indicates that the object can have both smi
  // and HeapObject elements.  Jump to the specified label if it does not.
  void CheckFastObjectElements(Register map,
                               Label* fail,
                               Label::Distance distance = Label::kFar);

  // Check if a map for a JSObject indicates that the object has fast smi only
  // elements.  Jump to the specified label if it does not.
968 969 970
  void CheckFastSmiElements(Register map,
                            Label* fail,
                            Label::Distance distance = Label::kFar);
971

972
  // Check to see if maybe_number can be stored as a double in
973 974 975
  // FastDoubleElements. If it can, store it at the index specified by index in
  // the FastDoubleElements array elements, otherwise jump to fail.  Note that
  // index must not be smi-tagged.
976 977
  void StoreNumberToDoubleElements(Register maybe_number,
                                   Register elements,
978
                                   Register index,
979
                                   XMMRegister xmm_scratch,
980 981
                                   Label* fail,
                                   int elements_offset = 0);
982

983 984
  // Compare an object's map with the specified map.
  void CompareMap(Register obj, Handle<Map> map);
985 986 987 988

  // Check if the map of an object is equal to a specified map and branch to
  // label if not. Skip the smi check if not required (object is known to be a
  // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
989
  // against maps that are ElementsKind transition maps of the specified map.
990 991 992
  void CheckMap(Register obj,
                Handle<Map> map,
                Label* fail,
993
                SmiCheckType smi_check_type);
994

danno@chromium.org's avatar
danno@chromium.org committed
995 996 997 998
  // Check if the map of an object is equal to a specified map and branch to a
  // specified target if equal. Skip the smi check if not required (object is
  // known to be a heap object)
  void DispatchMap(Register obj,
999
                   Register unused,
danno@chromium.org's avatar
danno@chromium.org committed
1000 1001 1002 1003
                   Handle<Map> map,
                   Handle<Code> success,
                   SmiCheckType smi_check_type);

1004 1005 1006 1007 1008 1009 1010 1011 1012
  // Check if the object in register heap_object is a string. Afterwards the
  // register map contains the object map and the register instance_type
  // contains the instance_type. The registers map and instance_type can be the
  // same in which case it contains the instance type afterwards. Either of the
  // registers map and instance_type can be the same as heap_object.
  Condition IsObjectStringType(Register heap_object,
                               Register map,
                               Register instance_type);

1013 1014 1015 1016 1017 1018 1019 1020 1021
  // Check if the object in register heap_object is a name. Afterwards the
  // register map contains the object map and the register instance_type
  // contains the instance_type. The registers map and instance_type can be the
  // same in which case it contains the instance type afterwards. Either of the
  // registers map and instance_type can be the same as heap_object.
  Condition IsObjectNameType(Register heap_object,
                             Register map,
                             Register instance_type);

1022 1023
  // FCmp compares and pops the two values on top of the FPU stack.
  // The flag results are similar to integer cmp, but requires unsigned
1024 1025 1026
  // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
  void FCmp();

1027 1028 1029 1030
  void ClampUint8(Register reg);

  void ClampDoubleToUint8(XMMRegister input_reg,
                          XMMRegister temp_xmm_reg,
1031
                          Register result_reg);
1032

1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
  void SlowTruncateToI(Register result_reg, Register input_reg,
      int offset = HeapNumber::kValueOffset - kHeapObjectTag);

  void TruncateHeapNumberToI(Register result_reg, Register input_reg);
  void TruncateDoubleToI(Register result_reg, XMMRegister input_reg);

  void DoubleToI(Register result_reg, XMMRegister input_reg,
      XMMRegister scratch, MinusZeroMode minus_zero_mode,
      Label* conversion_failed, Label::Distance dst = Label::kFar);

  void TaggedToI(Register result_reg, Register input_reg, XMMRegister temp,
      MinusZeroMode minus_zero_mode, Label* lost_precision,
      Label::Distance dst = Label::kFar);

1047
  void LoadUint32(XMMRegister dst, Register src);
1048

1049
  void LoadInstanceDescriptors(Register map, Register descriptors);
1050
  void EnumLength(Register dst, Register map);
1051
  void NumberOfOwnDescriptors(Register dst, Register map);
1052 1053 1054

  template<typename Field>
  void DecodeField(Register reg) {
1055
    static const int shift = Field::kShift;
1056
    static const int mask = Field::kMask >> Field::kShift;
1057 1058 1059
    if (shift != 0) {
      shrp(reg, Immediate(shift));
    }
1060
    andp(reg, Immediate(mask));
1061
  }
1062

1063 1064
  template<typename Field>
  void DecodeFieldToSmi(Register reg) {
1065 1066 1067 1068 1069 1070
    if (SmiValuesAre32Bits()) {
      andp(reg, Immediate(Field::kMask));
      shlp(reg, Immediate(kSmiShift - Field::kShift));
    } else {
      static const int shift = Field::kShift;
      static const int mask = (Field::kMask >> Field::kShift) << kSmiTagSize;
1071 1072 1073
      DCHECK(SmiValuesAre31Bits());
      DCHECK(kSmiShift == kSmiTagSize);
      DCHECK((mask & 0x80000000u) == 0);
1074 1075 1076 1077 1078 1079 1080
      if (shift < kSmiShift) {
        shlp(reg, Immediate(kSmiShift - shift));
      } else if (shift > kSmiShift) {
        sarp(reg, Immediate(shift - kSmiShift));
      }
      andp(reg, Immediate(mask));
    }
1081 1082
  }

1083 1084
  // Abort execution if argument is not a number, enabled via --debug-code.
  void AssertNumber(Register object);
1085

1086 1087
  // Abort execution if argument is a smi, enabled via --debug-code.
  void AssertNotSmi(Register object);
1088

1089 1090 1091
  // Abort execution if argument is not a smi, enabled via --debug-code.
  void AssertSmi(Register object);
  void AssertSmi(const Operand& object);
1092

1093
  // Abort execution if a 64 bit register containing a 32 bit payload does not
1094 1095
  // have zeros in the top 32 bits, enabled via --debug-code.
  void AssertZeroExtended(Register reg);
1096

1097 1098
  // Abort execution if argument is not a string, enabled via --debug-code.
  void AssertString(Register object);
1099

1100 1101 1102
  // Abort execution if argument is not a name, enabled via --debug-code.
  void AssertName(Register object);

1103 1104 1105 1106
  // Abort execution if argument is not undefined or an AllocationSite, enabled
  // via --debug-code.
  void AssertUndefinedOrAllocationSite(Register object);

1107 1108 1109 1110
  // Abort execution if argument is not the root value with the given index,
  // enabled via --debug-code.
  void AssertRootValue(Register src,
                       Heap::RootListIndex root_value_index,
1111
                       BailoutReason reason);
1112

1113 1114 1115
  // ---------------------------------------------------------------------------
  // Exception handling

1116
  // Push a new try handler and link it into try handler chain.
1117
  void PushTryHandler(StackHandler::Kind kind, int handler_index);
1118

1119 1120
  // Unlink the stack handler on top of the stack from the try handler chain.
  void PopTryHandler();
1121

1122 1123 1124 1125 1126
  // Activate the top handler in the try hander chain and pass the
  // thrown value.
  void Throw(Register value);

  // Propagate an uncatchable exception out of the current JS stack.
1127
  void ThrowUncatchable(Register value);
1128

1129 1130 1131 1132 1133
  // ---------------------------------------------------------------------------
  // Inline caching support

  // Generate code for checking access rights - used for security checks
  // on access to global objects across environments. The holder register
1134 1135
  // is left untouched, but the scratch register and kScratchRegister,
  // which must be different, are clobbered.
1136 1137 1138 1139
  void CheckAccessGlobalProxy(Register holder_reg,
                              Register scratch,
                              Label* miss);

1140 1141
  void GetNumberHash(Register r0, Register scratch);

1142 1143 1144 1145 1146 1147 1148 1149 1150
  void LoadFromNumberDictionary(Label* miss,
                                Register elements,
                                Register key,
                                Register r0,
                                Register r1,
                                Register r2,
                                Register result);


1151 1152 1153
  // ---------------------------------------------------------------------------
  // Allocation support

1154 1155 1156 1157 1158 1159 1160 1161 1162
  // Allocate an object in new space or old pointer space. If the given space
  // is exhausted control continues at the gc_required label. The allocated
  // object is returned in result and end of the new object is returned in
  // result_end. The register scratch can be passed as no_reg in which case
  // an additional object reference will be added to the reloc info. The
  // returned pointers in result and result_end have not yet been tagged as
  // heap objects. If result_contains_top_on_entry is true the content of
  // result is known to be the allocation top on entry (could be result_end
  // from a previous call). If result_contains_top_on_entry is true scratch
1163
  // should be no_reg as it is never used.
1164 1165 1166 1167 1168 1169
  void Allocate(int object_size,
                Register result,
                Register result_end,
                Register scratch,
                Label* gc_required,
                AllocationFlags flags);
1170

1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
  void Allocate(int header_size,
                ScaleFactor element_size,
                Register element_count,
                Register result,
                Register result_end,
                Register scratch,
                Label* gc_required,
                AllocationFlags flags);

  void Allocate(Register object_size,
                Register result,
                Register result_end,
                Register scratch,
                Label* gc_required,
                AllocationFlags flags);
1186 1187 1188 1189 1190 1191 1192

  // Undo allocation in new space. The object passed and objects allocated after
  // it will no longer be allocated. Make sure that no pointers are left to the
  // object(s) no longer allocated as they would be invalid when allocation is
  // un-done.
  void UndoAllocationInNewSpace(Register object);

1193 1194 1195 1196 1197
  // Allocate a heap number in new space with undefined value. Returns
  // tagged pointer in result register, or jumps to gc_required if new
  // space is full.
  void AllocateHeapNumber(Register result,
                          Register scratch,
1198 1199
                          Label* gc_required,
                          MutableMode mode = IMMUTABLE);
1200

1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217
  // Allocate a sequential string. All the header fields of the string object
  // are initialized.
  void AllocateTwoByteString(Register result,
                             Register length,
                             Register scratch1,
                             Register scratch2,
                             Register scratch3,
                             Label* gc_required);
  void AllocateAsciiString(Register result,
                           Register length,
                           Register scratch1,
                           Register scratch2,
                           Register scratch3,
                           Label* gc_required);

  // Allocate a raw cons string object. Only the map field of the result is
  // initialized.
1218
  void AllocateTwoByteConsString(Register result,
1219 1220 1221 1222 1223 1224 1225 1226
                          Register scratch1,
                          Register scratch2,
                          Label* gc_required);
  void AllocateAsciiConsString(Register result,
                               Register scratch1,
                               Register scratch2,
                               Label* gc_required);

1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
  // Allocate a raw sliced string object. Only the map field of the result is
  // initialized.
  void AllocateTwoByteSlicedString(Register result,
                            Register scratch1,
                            Register scratch2,
                            Label* gc_required);
  void AllocateAsciiSlicedString(Register result,
                                 Register scratch1,
                                 Register scratch2,
                                 Label* gc_required);

1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
  // ---------------------------------------------------------------------------
  // Support functions.

  // Check if result is zero and op is negative.
  void NegativeZeroTest(Register result, Register op, Label* then_label);

  // Check if result is zero and op is negative in code using jump targets.
  void NegativeZeroTest(CodeGenerator* cgen,
                        Register result,
                        Register op,
                        JumpTarget* then_target);

  // Check if result is zero and any of op1 and op2 are negative.
  // Register scratch is destroyed, and it must be different from op2.
  void NegativeZeroTest(Register result, Register op1, Register op2,
                        Register scratch, Label* then_label);

  // Try to get function prototype of a function and puts the value in
  // the result register. Checks that the function really is a
  // function and jumps to the miss label if the fast checks fail. The
1258
  // function register will be untouched; the other register may be
1259 1260 1261
  // clobbered.
  void TryGetFunctionPrototype(Register function,
                               Register result,
1262 1263
                               Label* miss,
                               bool miss_on_bound_function = false);
1264

1265 1266 1267 1268 1269 1270
  // Picks out an array index from the hash field.
  // Register use:
  //   hash - holds the index's hash. Clobbered.
  //   index - holds the overwritten index on exit.
  void IndexFromHash(Register hash, Register index);

1271 1272 1273
  // Find the function context up the context chain.
  void LoadContext(Register dst, int context_chain_length);

1274
  // Conditionally load the cached Array transitioned map of type
1275 1276
  // transitioned_kind from the native context if the map in register
  // map_in_out is the cached Array map in the native context of
1277 1278 1279 1280 1281 1282 1283 1284
  // expected_kind.
  void LoadTransitionedArrayMapConditional(
      ElementsKind expected_kind,
      ElementsKind transitioned_kind,
      Register map_in_out,
      Register scratch,
      Label* no_map_match);

1285 1286 1287 1288 1289 1290 1291
  // Load the global function with the given index.
  void LoadGlobalFunction(int index, Register function);

  // Load the initial map from the global function. The registers
  // function and map can be the same.
  void LoadGlobalFunctionInitialMap(Register function, Register map);

1292 1293 1294 1295
  // ---------------------------------------------------------------------------
  // Runtime calls

  // Call a code stub.
1296
  void CallStub(CodeStub* stub, TypeFeedbackId ast_id = TypeFeedbackId::None());
1297

1298 1299 1300
  // Tail call a code stub (jump).
  void TailCallStub(CodeStub* stub);

1301 1302 1303 1304
  // Return from a code stub after popping its arguments.
  void StubReturn(int argc);

  // Call a runtime routine.
1305 1306 1307
  void CallRuntime(const Runtime::Function* f,
                   int num_arguments,
                   SaveFPRegsMode save_doubles = kDontSaveFPRegs);
1308

1309
  // Call a runtime function and save the value of XMM registers.
1310 1311 1312 1313
  void CallRuntimeSaveDoubles(Runtime::FunctionId id) {
    const Runtime::Function* function = Runtime::FunctionForId(id);
    CallRuntime(function, function->nargs, kSaveFPRegs);
  }
1314

1315
  // Convenience function: Same as above, but takes the fid instead.
1316 1317 1318 1319
  void CallRuntime(Runtime::FunctionId id,
                   int num_arguments,
                   SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
    CallRuntime(Runtime::FunctionForId(id), num_arguments, save_doubles);
1320
  }
1321

1322 1323 1324 1325
  // Convenience function: call an external reference.
  void CallExternalReference(const ExternalReference& ext,
                             int num_arguments);

1326
  // Tail call of a runtime routine (jump).
serya@chromium.org's avatar
serya@chromium.org committed
1327 1328 1329 1330 1331 1332 1333 1334
  // Like JumpToExternalReference, but also takes care of passing the number
  // of parameters.
  void TailCallExternalReference(const ExternalReference& ext,
                                 int num_arguments,
                                 int result_size);

  // Convenience function: tail call a runtime routine (jump).
  void TailCallRuntime(Runtime::FunctionId fid,
1335 1336
                       int num_arguments,
                       int result_size);
1337

1338
  // Jump to a runtime routine.
serya@chromium.org's avatar
serya@chromium.org committed
1339
  void JumpToExternalReference(const ExternalReference& ext, int result_size);
1340

1341 1342 1343 1344
  // Prepares stack to put arguments (aligns and so on).  WIN64 calling
  // convention requires to put the pointer to the return value slot into
  // rcx (rcx must be preserverd until CallApiFunctionAndReturn).  Saves
  // context (rsi).  Clobbers rax.  Allocates arg_stack_space * kPointerSize
1345
  // inside the exit frame (not GCed) accessible via StackSpaceOperand.
1346
  void PrepareCallApiFunction(int arg_stack_space);
1347

1348 1349 1350 1351
  // Calls an API function.  Allocates HandleScope, extracts returned value
  // from handle and propagates exceptions.  Clobbers r14, r15, rbx and
  // caller-save registers.  Restores context.  On return removes
  // stack_space * kPointerSize (GCed).
1352
  void CallApiFunctionAndReturn(Register function_address,
1353
                                ExternalReference thunk_ref,
1354
                                Register thunk_last_arg,
1355
                                int stack_space,
1356 1357
                                Operand return_value_operand,
                                Operand* context_restore_operand);
1358

1359
  // Before calling a C-function from generated code, align arguments on stack.
1360
  // After aligning the frame, arguments must be stored in rsp[0], rsp[8],
1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378
  // etc., not pushed. The argument count assumes all arguments are word sized.
  // The number of slots reserved for arguments depends on platform. On Windows
  // stack slots are reserved for the arguments passed in registers. On other
  // platforms stack slots are only reserved for the arguments actually passed
  // on the stack.
  void PrepareCallCFunction(int num_arguments);

  // Calls a C function and cleans up the space for arguments allocated
  // by PrepareCallCFunction. The called function is not allowed to trigger a
  // garbage collection, since that might move the code and invalidate the
  // return address (unless this is somehow accounted for by the called
  // function).
  void CallCFunction(ExternalReference function, int num_arguments);
  void CallCFunction(Register function, int num_arguments);

  // Calculate the number of stack slots to reserve for arguments when calling a
  // C function.
  int ArgumentStackSlotsForCFunctionCall(int num_arguments);
1379 1380 1381 1382 1383 1384

  // ---------------------------------------------------------------------------
  // Utilities

  void Ret();

1385 1386 1387 1388
  // Return and drop arguments from stack, where the number of arguments
  // may be bigger than 2^16 - 1.  Requires a scratch register.
  void Ret(int bytes_dropped, Register scratch);

1389
  Handle<Object> CodeObject() {
1390
    DCHECK(!code_object_.is_null());
1391 1392
    return code_object_;
  }
1393

1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
  // Copy length bytes from source to destination.
  // Uses scratch register internally (if you have a low-eight register
  // free, do use it, otherwise kScratchRegister will be used).
  // The min_length is a minimum limit on the value that length will have.
  // The algorithm has some special cases that might be omitted if the string
  // is known to always be long.
  void CopyBytes(Register destination,
                 Register source,
                 Register length,
                 int min_length = 0,
                 Register scratch = kScratchRegister);

1406 1407 1408 1409 1410 1411 1412
  // Initialize fields with filler values.  Fields starting at |start_offset|
  // not including end_offset are overwritten with the value in |filler|.  At
  // the end the loop, |start_offset| takes the value of |end_offset|.
  void InitializeFieldsWithFiller(Register start_offset,
                                  Register end_offset,
                                  Register filler);

1413

1414
  // Emit code for a truncating division by a constant. The dividend register is
1415
  // unchanged, the result is in rdx, and rax gets clobbered.
1416
  void TruncatingDiv(Register dividend, int32_t divisor);
1417

1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
  // ---------------------------------------------------------------------------
  // StatsCounter support

  void SetCounter(StatsCounter* counter, int value);
  void IncrementCounter(StatsCounter* counter, int value);
  void DecrementCounter(StatsCounter* counter, int value);


  // ---------------------------------------------------------------------------
  // Debugging

  // Calls Abort(msg) if the condition cc is not satisfied.
  // Use --debug_code to enable.
1431
  void Assert(Condition cc, BailoutReason reason);
1432

1433 1434
  void AssertFastElements(Register elements);

1435
  // Like Assert(), but always enabled.
1436
  void Check(Condition cc, BailoutReason reason);
1437 1438

  // Print a message to stdout and abort execution.
1439
  void Abort(BailoutReason msg);
1440

1441 1442 1443
  // Check that the stack is aligned.
  void CheckStackAlignment();

1444 1445 1446
  // Verify restrictions about code generated in stubs.
  void set_generating_stub(bool value) { generating_stub_ = value; }
  bool generating_stub() { return generating_stub_; }
1447 1448 1449
  void set_has_frame(bool value) { has_frame_ = value; }
  bool has_frame() { return has_frame_; }
  inline bool AllowThisStubCall(CodeStub* stub);
1450

1451 1452 1453 1454
  static int SafepointRegisterStackIndex(Register reg) {
    return SafepointRegisterStackIndex(reg.code());
  }

1455 1456 1457 1458
  // Activation support.
  void EnterFrame(StackFrame::Type type);
  void LeaveFrame(StackFrame::Type type);

1459 1460 1461 1462 1463
  // Expects object in rax and returns map with validated enum cache
  // in rax.  Assumes that any other register can be used as a scratch.
  void CheckEnumCache(Register null_value,
                      Label* call_runtime);

1464 1465
  // AllocationMemento support. Arrays may have an associated
  // AllocationMemento object that can be checked for in order to pretransition
1466 1467 1468
  // to another type.
  // On entry, receiver_reg should point to the array object.
  // scratch_reg gets clobbered.
1469
  // If allocation info is present, condition flags are set to equal.
1470
  void TestJSArrayForAllocationMemento(Register receiver_reg,
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482
                                       Register scratch_reg,
                                       Label* no_memento_found);

  void JumpIfJSArrayHasAllocationMemento(Register receiver_reg,
                                         Register scratch_reg,
                                         Label* memento_found) {
    Label no_memento_found;
    TestJSArrayForAllocationMemento(receiver_reg, scratch_reg,
                                    &no_memento_found);
    j(equal, memento_found);
    bind(&no_memento_found);
  }
1483

1484 1485 1486 1487
  // Jumps to found label if a prototype map has dictionary elements.
  void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0,
                                        Register scratch1, Label* found);

1488
 private:
1489
  // Order general registers are pushed by Pushad.
1490
  // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15.
1491
  static const int kSafepointPushRegisterIndices[Register::kNumRegisters];
1492
  static const int kNumSafepointSavedRegisters = 11;
1493
  static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
1494

1495
  bool generating_stub_;
1496
  bool has_frame_;
1497
  bool root_array_available_;
1498 1499 1500 1501 1502

  // Returns a register holding the smi value. The register MUST NOT be
  // modified. It may be the "smi 1 constant" register.
  Register GetSmiConstant(Smi* value);

1503
  int64_t RootRegisterDelta(ExternalReference other);
1504

1505 1506 1507
  // Moves the smi value to the destination register.
  void LoadSmiConstant(Register dst, Smi* value);

1508 1509
  // This handle will be patched with the code object on installation.
  Handle<Object> code_object_;
1510 1511 1512 1513 1514

  // Helper functions for generating invokes.
  void InvokePrologue(const ParameterCount& expected,
                      const ParameterCount& actual,
                      Handle<Code> code_constant,
1515
                      Register code_register,
1516
                      Label* done,
1517
                      bool* definitely_mismatches,
1518
                      InvokeFlag flag,
1519
                      Label::Distance near_jump = Label::kFar,
1520
                      const CallWrapper& call_wrapper = NullCallWrapper());
1521

1522
  void EnterExitFramePrologue(bool save_rax);
1523 1524 1525

  // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack
  // accessible via StackSpaceOperand.
1526
  void EnterExitFrameEpilogue(int arg_stack_space, bool save_doubles);
1527

1528
  void LeaveExitFrameEpilogue(bool restore_context);
1529

1530
  // Allocation support helpers.
1531 1532 1533
  // Loads the top of new-space into the result register.
  // Otherwise the address of the new-space top is loaded into scratch (if
  // scratch is valid), and the new-space top is loaded into result.
1534 1535
  void LoadAllocationTopHelper(Register result,
                               Register scratch,
1536
                               AllocationFlags flags);
1537

1538 1539 1540 1541 1542
  void MakeSureDoubleAlignedHelper(Register result,
                                   Register scratch,
                                   Label* gc_required,
                                   AllocationFlags flags);

1543 1544
  // Update allocation top with value in result_end register.
  // If scratch is valid, it contains the address of the allocation top.
1545 1546 1547
  void UpdateAllocationTopHelper(Register result_end,
                                 Register scratch,
                                 AllocationFlags flags);
1548

1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562
  // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
  void InNewSpace(Register object,
                  Register scratch,
                  Condition cc,
                  Label* branch,
                  Label::Distance distance = Label::kFar);

  // Helper for finding the mark bits for an address.  Afterwards, the
  // bitmap register points at the word with the mark bits and the mask
  // the position of the first bit.  Uses rcx as scratch and leaves addr_reg
  // unchanged.
  inline void GetMarkBits(Register addr_reg,
                          Register bitmap_reg,
                          Register mask_reg);
1563

1564 1565 1566 1567
  // Helper for throwing exceptions.  Compute a handler address and jump to
  // it.  See the implementation for register usage.
  void JumpToHandlerEntry();

1568 1569 1570 1571 1572 1573
  // Compute memory operands for safepoint stack slots.
  Operand SafepointRegisterSlot(Register reg);
  static int SafepointRegisterStackIndex(int reg_code) {
    return kNumSafepointRegisters - kSafepointPushRegisterIndices[reg_code] - 1;
  }

1574
  // Needs access to SafepointRegisterStackIndex for compiled frame
1575
  // traversal.
1576
  friend class StandardFrame;
1577 1578 1579
};


1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599
// The code patcher is used to patch (typically) small parts of code e.g. for
// debugging and other types of instrumentation. When using the code patcher
// the exact number of bytes specified must be emitted. Is not legal to emit
// relocation information. If any of these constraints are violated it causes
// an assertion.
class CodePatcher {
 public:
  CodePatcher(byte* address, int size);
  virtual ~CodePatcher();

  // Macro assembler to emit code.
  MacroAssembler* masm() { return &masm_; }

 private:
  byte* address_;  // The address of the code being patched.
  int size_;  // Number of bytes of the expected patch size.
  MacroAssembler masm_;  // Macro assembler used to generate the code.
};


1600 1601 1602 1603
// -----------------------------------------------------------------------------
// Static helper functions.

// Generate an Operand for loading a field from an object.
1604
inline Operand FieldOperand(Register object, int offset) {
1605 1606 1607 1608 1609
  return Operand(object, offset - kHeapObjectTag);
}


// Generate an Operand for loading an indexed field from an object.
1610 1611 1612 1613
inline Operand FieldOperand(Register object,
                            Register index,
                            ScaleFactor scale,
                            int offset) {
1614 1615 1616 1617
  return Operand(object, index, scale, offset - kHeapObjectTag);
}


1618
inline Operand ContextOperand(Register context, int index) {
1619 1620 1621 1622
  return Operand(context, Context::SlotOffset(index));
}


1623
inline Operand GlobalObjectOperand() {
1624
  return ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX);
1625 1626 1627
}


1628
// Provides access to exit frame stack space (not GCed).
1629
inline Operand StackSpaceOperand(int index) {
1630 1631 1632 1633 1634 1635 1636 1637 1638
#ifdef _WIN64
  const int kShaddowSpace = 4;
  return Operand(rsp, (index + kShaddowSpace) * kPointerSize);
#else
  return Operand(rsp, index * kPointerSize);
#endif
}


1639 1640 1641 1642
inline Operand StackOperandForReturnAddress(int32_t disp) {
  return Operand(rsp, disp);
}

1643

1644 1645 1646 1647 1648
#ifdef GENERATED_CODE_COVERAGE
extern void LogGeneratedCodeCoverage(const char* file_line);
#define CODE_COVERAGE_STRINGIFY(x) #x
#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
1649 1650 1651 1652
#define ACCESS_MASM(masm) {                                                  \
    Address x64_coverage_function = FUNCTION_ADDR(LogGeneratedCodeCoverage); \
    masm->pushfq();                                                          \
    masm->Pushad();                                                          \
1653
    masm->Push(Immediate(reinterpret_cast<int>(&__FILE_LINE__)));            \
1654
    masm->Call(x64_coverage_function, RelocInfo::EXTERNAL_REFERENCE);        \
1655
    masm->Pop(rax);                                                          \
1656 1657 1658
    masm->Popad();                                                           \
    masm->popfq();                                                           \
  }                                                                          \
1659 1660 1661 1662 1663 1664 1665 1666
  masm->
#else
#define ACCESS_MASM(masm) masm->
#endif

} }  // namespace v8::internal

#endif  // V8_X64_MACRO_ASSEMBLER_X64_H_