assembler.h 36.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
// Copyright (c) 1994-2006 Sun Microsystems Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// - Redistribution in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// - Neither the name of Sun Microsystems or the names of contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// The original source code covered by the above license above has been
// modified significantly by Google Inc.
33
// Copyright 2012 the V8 project authors. All rights reserved.
34 35 36 37

#ifndef V8_ASSEMBLER_H_
#define V8_ASSEMBLER_H_

38 39
#include "v8.h"

40
#include "allocation.h"
41
#include "builtins.h"
42
#include "gdb-jit.h"
43
#include "isolate.h"
44
#include "runtime.h"
45
#include "token.h"
46

47
namespace v8 {
48 49 50

class ApiFunction;

51
namespace internal {
52

53
class StatsCounter;
54 55 56 57 58
// -----------------------------------------------------------------------------
// Platform independent assembler base class.

class AssemblerBase: public Malloced {
 public:
59 60
  AssemblerBase(Isolate* isolate, void* buffer, int buffer_size);
  virtual ~AssemblerBase();
61 62

  Isolate* isolate() const { return isolate_; }
63 64
  int jit_cookie() const { return jit_cookie_; }

65 66 67
  bool emit_debug_code() const { return emit_debug_code_; }
  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }

68 69
  bool predictable_code_size() const { return predictable_code_size_; }
  void set_predictable_code_size(bool value) { predictable_code_size_ = value; }
70

71 72 73 74 75 76 77 78
  uint64_t enabled_cpu_features() const { return enabled_cpu_features_; }
  void set_enabled_cpu_features(uint64_t features) {
    enabled_cpu_features_ = features;
  }
  bool IsEnabled(CpuFeature f) {
    return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0;
  }

79 80 81 82
  // Overwrite a host NaN with a quiet target NaN.  Used by mksnapshot for
  // cross-snapshotting.
  static void QuietNaN(HeapObject* nan) { }

83 84 85 86 87 88 89 90 91 92 93 94 95 96
  int pc_offset() const { return static_cast<int>(pc_ - buffer_); }

  static const int kMinimalBufferSize = 4*KB;

 protected:
  // The buffer into which code and relocation info are generated. It could
  // either be owned by the assembler or be provided externally.
  byte* buffer_;
  int buffer_size_;
  bool own_buffer_;

  // The program counter, which points into the buffer above and moves forward.
  byte* pc_;

97 98
 private:
  Isolate* isolate_;
99
  int jit_cookie_;
100
  uint64_t enabled_cpu_features_;
101
  bool emit_debug_code_;
102 103 104 105 106 107 108 109
  bool predictable_code_size_;
};


// Avoids using instructions that vary in size in unpredictable ways between the
// snapshot and the running VM.
class PredictableCodeSizeScope {
 public:
110 111
  PredictableCodeSizeScope(AssemblerBase* assembler, int expected_size);
  ~PredictableCodeSizeScope();
112 113 114

 private:
  AssemblerBase* assembler_;
115 116
  int expected_size_;
  int start_offset_;
117
  bool old_value_;
118 119
};

120

121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
// Enable a specified feature within a scope.
class CpuFeatureScope BASE_EMBEDDED {
 public:
#ifdef DEBUG
  CpuFeatureScope(AssemblerBase* assembler, CpuFeature f);
  ~CpuFeatureScope();

 private:
  AssemblerBase* assembler_;
  uint64_t old_enabled_;
#else
  CpuFeatureScope(AssemblerBase* assembler, CpuFeature f) {}
#endif
};


137 138 139 140 141 142
// -----------------------------------------------------------------------------
// Labels represent pc locations; they are typically jump or call targets.
// After declaration, a label can be freely used to denote known or (yet)
// unknown pc location. Assembler::bind() is used to bind a label to the
// current pc. A label can be bound only once.

143
class Label BASE_EMBEDDED {
144
 public:
145 146 147 148 149 150 151 152
  enum Distance {
    kNear, kFar
  };

  INLINE(Label()) {
    Unuse();
    UnuseNear();
  }
153

154 155 156 157 158 159 160
  INLINE(~Label()) {
    ASSERT(!is_linked());
    ASSERT(!is_near_linked());
  }

  INLINE(void Unuse()) { pos_ = 0; }
  INLINE(void UnuseNear()) { near_link_pos_ = 0; }
161

162 163 164
  INLINE(bool is_bound() const) { return pos_ <  0; }
  INLINE(bool is_unused() const) { return pos_ == 0 && near_link_pos_ == 0; }
  INLINE(bool is_linked() const) { return pos_ >  0; }
165
  INLINE(bool is_near_linked() const) { return near_link_pos_ > 0; }
166 167 168 169

  // Returns the position of bound or linked labels. Cannot be used
  // for unused labels.
  int pos() const;
170
  int near_link_pos() const { return near_link_pos_ - 1; }
171 172 173 174 175 176 177 178 179 180

 private:
  // pos_ encodes both the binding state (via its sign)
  // and the binding position (via its value) of a label.
  //
  // pos_ <  0  bound label, pos() returns the jump target position
  // pos_ == 0  unused label
  // pos_ >  0  linked label, pos() returns the last reference position
  int pos_;

181 182 183
  // Behaves like |pos_| in the "> 0" case, but for near jumps to this label.
  int near_link_pos_;

184 185 186 187
  void bind_to(int pos)  {
    pos_ = -pos - 1;
    ASSERT(is_bound());
  }
188 189 190 191 192 193 194 195
  void link_to(int pos, Distance distance = kFar) {
    if (distance == kNear) {
      near_link_pos_ = pos + 1;
      ASSERT(is_near_linked());
    } else {
      pos_ = pos + 1;
      ASSERT(is_linked());
    }
196 197 198
  }

  friend class Assembler;
199
  friend class RegexpAssembler;
200
  friend class Displacement;
201
  friend class RegExpMacroAssemblerIrregexp;
202 203 204
};


205 206 207
enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs };


208 209 210
// -----------------------------------------------------------------------------
// Relocation information

kasperl@chromium.org's avatar
kasperl@chromium.org committed
211

212 213 214 215 216 217 218 219 220
// Relocation information consists of the address (pc) of the datum
// to which the relocation information applies, the relocation mode
// (rmode), and an optional data field. The relocation mode may be
// "descriptive" and not indicate a need for relocation, but simply
// describe a property of the datum. Such rmodes are useful for GC
// and nice disassembly output.

class RelocInfo BASE_EMBEDDED {
 public:
221 222 223 224 225 226 227 228 229 230 231
  // The constant kNoPosition is used with the collecting of source positions
  // in the relocation information. Two types of source positions are collected
  // "position" (RelocMode position) and "statement position" (RelocMode
  // statement_position). The "position" is collected at places in the source
  // code which are of interest when making stack traces to pin-point the source
  // location of a stack frame as close as possible. The "statement position" is
  // collected at the beginning at each statement, and is used to indicate
  // possible break locations. kNoPosition is used to indicate an
  // invalid/uninitialized position value.
  static const int kNoPosition = -1;

232 233 234 235
  // This string is used to add padding comments to the reloc info in cases
  // where we are not sure to have enough space for patching in during
  // lazy deoptimization. This is the case if we have indirect calls for which
  // we do not normally record relocation info.
236
  static const char* const kFillerCommentString;
237

238 239
  // The minimum size of a comment is equal to three bytes for the extra tagged
  // pc + the tag for the data, and kPointerSize for the actual pointer to the
240
  // comment.
241
  static const int kMinRelocCommentSize = 3 + kPointerSize;
242 243 244 245

  // The maximum size for a call instruction including pc-jump.
  static const int kMaxCallSize = 6;

246 247 248
  // The maximum pc delta that will use the short encoding.
  static const int kMaxSmallPCDelta;

249 250
  enum Mode {
    // Please note the order is important (see IsCodeTarget, IsGCRelocMode).
251 252
    CODE_TARGET,  // Code target which is not any of the above.
    CODE_TARGET_WITH_ID,
253
    CONSTRUCT_CALL,  // code target that is a call to a JavaScript constructor.
254
    CODE_TARGET_CONTEXT,  // Code target used for contextual loads and stores.
255
    DEBUG_BREAK,  // Code target for the debugger statement.
256
    EMBEDDED_OBJECT,
257 258
    GLOBAL_PROPERTY_CELL,

259 260 261 262 263 264
    // Everything after runtime_entry (inclusive) is not GC'ed.
    RUNTIME_ENTRY,
    JS_RETURN,  // Marks start of the ExitJSFrame code.
    COMMENT,
    POSITION,  // See comment for kNoPosition above.
    STATEMENT_POSITION,  // See comment for kNoPosition above.
265
    DEBUG_BREAK_SLOT,  // Additional code inserted for debug break slot.
266 267 268
    EXTERNAL_REFERENCE,  // The address of an external C++ function.
    INTERNAL_REFERENCE,  // An address inside the same function.

269 270 271 272
    // Marks a constant pool. Only used on ARM.
    // It uses a custom noncompact encoding.
    CONST_POOL,

273 274
    // add more as needed
    // Pseudo-types
275
    NUMBER_OF_MODES,  // There are at most 15 modes with noncompact encoding.
276
    NONE32,  // never recorded 32-bit value
277
    NONE64,  // never recorded 64-bit value
278 279 280 281 282 283
    CODE_AGE_SEQUENCE,  // Not stored in RelocInfo array, used explictly by
                        // code aging.
    FIRST_REAL_RELOC_MODE = CODE_TARGET,
    LAST_REAL_RELOC_MODE = CONST_POOL,
    FIRST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE,
    LAST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE,
284 285 286
    LAST_CODE_ENUM = DEBUG_BREAK,
    LAST_GCED_ENUM = GLOBAL_PROPERTY_CELL,
    // Modes <= LAST_COMPACT_ENUM are guaranteed to have compact encoding.
287 288
    LAST_COMPACT_ENUM = CODE_TARGET_WITH_ID,
    LAST_STANDARD_NONCOMPACT_ENUM = INTERNAL_REFERENCE
289 290 291
  };


292
  RelocInfo() {}
293 294 295

  RelocInfo(byte* pc, Mode rmode, intptr_t data, Code* host)
      : pc_(pc), rmode_(rmode), data_(data), host_(host) {
296
  }
297 298 299
  RelocInfo(byte* pc, double data64)
      : pc_(pc), rmode_(NONE64), data64_(data64), host_(NULL) {
  }
300

301 302 303 304 305 306 307 308 309
  static inline bool IsRealRelocMode(Mode mode) {
    return mode >= FIRST_REAL_RELOC_MODE &&
        mode <= LAST_REAL_RELOC_MODE;
  }
  static inline bool IsPseudoRelocMode(Mode mode) {
    ASSERT(!IsRealRelocMode(mode));
    return mode >= FIRST_PSEUDO_RELOC_MODE &&
        mode <= LAST_PSEUDO_RELOC_MODE;
  }
310 311 312 313 314 315
  static inline bool IsConstructCall(Mode mode) {
    return mode == CONSTRUCT_CALL;
  }
  static inline bool IsCodeTarget(Mode mode) {
    return mode <= LAST_CODE_ENUM;
  }
316 317 318
  static inline bool IsEmbeddedObject(Mode mode) {
    return mode == EMBEDDED_OBJECT;
  }
319 320 321
  static inline bool IsRuntimeEntry(Mode mode) {
    return mode == RUNTIME_ENTRY;
  }
322 323 324 325 326 327 328 329 330 331
  // Is the relocation mode affected by GC?
  static inline bool IsGCRelocMode(Mode mode) {
    return mode <= LAST_GCED_ENUM;
  }
  static inline bool IsJSReturn(Mode mode) {
    return mode == JS_RETURN;
  }
  static inline bool IsComment(Mode mode) {
    return mode == COMMENT;
  }
332 333 334
  static inline bool IsConstPool(Mode mode) {
    return mode == CONST_POOL;
  }
335 336 337 338 339 340 341 342 343 344 345 346
  static inline bool IsPosition(Mode mode) {
    return mode == POSITION || mode == STATEMENT_POSITION;
  }
  static inline bool IsStatementPosition(Mode mode) {
    return mode == STATEMENT_POSITION;
  }
  static inline bool IsExternalReference(Mode mode) {
    return mode == EXTERNAL_REFERENCE;
  }
  static inline bool IsInternalReference(Mode mode) {
    return mode == INTERNAL_REFERENCE;
  }
347 348 349
  static inline bool IsDebugBreakSlot(Mode mode) {
    return mode == DEBUG_BREAK_SLOT;
  }
350
  static inline bool IsNone(Mode mode) {
351
    return mode == NONE32 || mode == NONE64;
352
  }
353 354 355
  static inline bool IsCodeAgeSequence(Mode mode) {
    return mode == CODE_AGE_SEQUENCE;
  }
356 357
  static inline int ModeMask(Mode mode) { return 1 << mode; }

358
  // Accessors
359
  byte* pc() const { return pc_; }
360
  void set_pc(byte* pc) { pc_ = pc; }
361
  Mode rmode() const {  return rmode_; }
362
  intptr_t data() const { return data_; }
363
  double data64() const { return data64_; }
364
  Code* host() const { return host_; }
365 366

  // Apply a relocation by delta bytes
367
  INLINE(void apply(intptr_t delta));
368

369
  // Is the pointer this relocation info refers to coded like a plain pointer
370
  // or is it strange in some way (e.g. relative or patched into a series of
371 372 373
  // instructions).
  bool IsCodedSpecially();

374 375
  // Read/modify the code target in the branch/call instruction
  // this relocation applies to;
376
  // can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
377
  INLINE(Address target_address());
378 379
  INLINE(void set_target_address(Address target,
                                 WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
380
  INLINE(Object* target_object());
381
  INLINE(Handle<Object> target_object_handle(Assembler* origin));
382
  INLINE(Object** target_object_address());
383 384
  INLINE(void set_target_object(Object* target,
                                WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
385 386 387 388
  INLINE(Address target_runtime_entry(Assembler* origin));
  INLINE(void set_target_runtime_entry(Address target,
                                       WriteBarrierMode mode =
                                           UPDATE_WRITE_BARRIER));
389 390
  INLINE(JSGlobalPropertyCell* target_cell());
  INLINE(Handle<JSGlobalPropertyCell> target_cell_handle());
391 392
  INLINE(void set_target_cell(JSGlobalPropertyCell* cell,
                              WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
393 394
  INLINE(Code* code_age_stub());
  INLINE(void set_code_age_stub(Code* stub));
395

396 397 398 399 400 401
  // Read the address of the word containing the target_address in an
  // instruction stream.  What this means exactly is architecture-independent.
  // The only architecture-independent user of this function is the serializer.
  // The serializer uses it to find out how many raw bytes of instruction to
  // output before the next target.  Architecture-independent code shouldn't
  // dereference the pointer it gets back from this.
402
  INLINE(Address target_address_address());
403 404 405 406 407 408 409 410 411 412
  // This indicates how much space a target takes up when deserializing a code
  // stream.  For most architectures this is just the size of a pointer.  For
  // an instruction like movw/movt where the target bits are mixed into the
  // instruction bits the size of the target will be zero, indicating that the
  // serializer should not step forwards in memory after a target is resolved
  // and written.  In this case the target_address_address function above
  // should return the end of the instructions to be patched, allowing the
  // deserializer to deserialize the instructions as raw bytes and put them in
  // place, ready to be patched with the target.
  INLINE(int target_address_size());
413

414 415 416 417 418 419 420 421 422 423 424
  // Read/modify the reference in the instruction this relocation
  // applies to; can only be called if rmode_ is external_reference
  INLINE(Address* target_reference_address());

  // Read/modify the address of a call instruction. This is used to relocate
  // the break points where straight-line code is patched with a call
  // instruction.
  INLINE(Address call_address());
  INLINE(void set_call_address(Address target));
  INLINE(Object* call_object());
  INLINE(void set_call_object(Object* target));
425
  INLINE(Object** call_object_address());
426

427
  template<typename StaticVisitor> inline void Visit(Heap* heap);
428 429
  inline void Visit(ObjectVisitor* v);

430
  // Patch the code with some other code.
431
  void PatchCode(byte* instructions, int instruction_count);
432 433

  // Patch the code with a call.
434
  void PatchCodeWithCall(Address target, int guard_bytes);
435 436 437 438

  // Check whether this return sequence has been patched
  // with a call to the debugger.
  INLINE(bool IsPatchedReturnSequence());
439

440 441 442 443
  // Check whether this debug break slot has been patched with a call to the
  // debugger.
  INLINE(bool IsPatchedDebugBreakSlotSequence());

444 445 446 447 448 449
#ifdef DEBUG
  // Check whether the given code contains relocation information that
  // either is position-relative or movable by the garbage collector.
  static bool RequiresRelocation(const CodeDesc& desc);
#endif

450 451
#ifdef ENABLE_DISASSEMBLER
  // Printing
452
  static const char* RelocModeName(Mode rmode);
453
  void Print(Isolate* isolate, FILE* out);
454
#endif  // ENABLE_DISASSEMBLER
455
#ifdef VERIFY_HEAP
456 457 458
  void Verify();
#endif

459 460
  static const int kCodeTargetMask = (1 << (LAST_CODE_ENUM + 1)) - 1;
  static const int kPositionMask = 1 << POSITION | 1 << STATEMENT_POSITION;
461 462
  static const int kDataMask =
      (1 << CODE_TARGET_WITH_ID) | kPositionMask | (1 << COMMENT);
463 464 465 466 467 468 469 470
  static const int kApplyMask;  // Modes affected by apply. Depends on arch.

 private:
  // On ARM, note that pc_ is the address of the constant pool entry
  // to be relocated and not the address of the instruction
  // referencing the constant pool entry (except when rmode_ ==
  // comment).
  byte* pc_;
471
  Mode rmode_;
472 473 474 475
  union {
    intptr_t data_;
    double data64_;
  };
476
  Code* host_;
477
  // Code and Embedded Object pointers on some platforms are stored split
478 479
  // across two consecutive 32-bit instructions. Heap management
  // routines expect to access these pointers indirectly. The following
480
  // location provides a place for these pointers to exist naturally
481
  // when accessed via the Iterator.
482
  Object* reconstructed_obj_ptr_;
483
  // External-reference pointers are also split across instruction-pairs
484
  // on some platforms, but are accessed via indirect pointers. This location
485 486 487
  // provides a place for that pointer to exist naturally. Its address
  // is returned by RelocInfo::target_reference_address().
  Address reconstructed_adr_ptr_;
488 489 490 491 492 493 494 495
  friend class RelocIterator;
};


// RelocInfoWriter serializes a stream of relocation info. It writes towards
// lower addresses.
class RelocInfoWriter BASE_EMBEDDED {
 public:
496 497 498 499 500 501 502 503
  RelocInfoWriter() : pos_(NULL),
                      last_pc_(NULL),
                      last_id_(0),
                      last_position_(0) {}
  RelocInfoWriter(byte* pos, byte* pc) : pos_(pos),
                                         last_pc_(pc),
                                         last_id_(0),
                                         last_position_(0) {}
504 505 506 507 508 509 510 511 512 513 514 515 516

  byte* pos() const { return pos_; }
  byte* last_pc() const { return last_pc_; }

  void Write(const RelocInfo* rinfo);

  // Update the state of the stream after reloc info buffer
  // and/or code is moved while the stream is active.
  void Reposition(byte* pos, byte* pc) {
    pos_ = pos;
    last_pc_ = pc;
  }

517 518 519 520 521 522
  // Max size (bytes) of a written RelocInfo. Longest encoding is
  // ExtraTag, VariableLengthPCJump, ExtraTag, pc_delta, ExtraTag, data_delta.
  // On ia32 and arm this is 1 + 4 + 1 + 1 + 1 + 4 = 12.
  // On x64 this is 1 + 4 + 1 + 1 + 1 + 8 == 16;
  // Here we use the maximum of the two.
  static const int kMaxSize = 16;
523 524 525 526 527

 private:
  inline uint32_t WriteVariableLengthPCJump(uint32_t pc_delta);
  inline void WriteTaggedPC(uint32_t pc_delta, int tag);
  inline void WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag);
528
  inline void WriteExtraTaggedIntData(int data_delta, int top_tag);
529
  inline void WriteExtraTaggedConstPoolData(int data);
530 531
  inline void WriteExtraTaggedData(intptr_t data_delta, int top_tag);
  inline void WriteTaggedData(intptr_t data_delta, int tag);
532 533 534 535
  inline void WriteExtraTag(int extra_tag, int top_tag);

  byte* pos_;
  byte* last_pc_;
536 537
  int last_id_;
  int last_position_;
538
  DISALLOW_COPY_AND_ASSIGN(RelocInfoWriter);
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
};


// A RelocIterator iterates over relocation information.
// Typical use:
//
//   for (RelocIterator it(code); !it.done(); it.next()) {
//     // do something with it.rinfo() here
//   }
//
// A mask can be specified to skip unwanted modes.
class RelocIterator: public Malloced {
 public:
  // Create a new iterator positioned at
  // the beginning of the reloc info.
  // Relocation information with mode k is included in the
  // iteration iff bit k of mode_mask is set.
  explicit RelocIterator(Code* code, int mode_mask = -1);
  explicit RelocIterator(const CodeDesc& desc, int mode_mask = -1);

  // Iteration
560
  bool done() const { return done_; }
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578
  void next();

  // Return pointer valid until next next().
  RelocInfo* rinfo() {
    ASSERT(!done());
    return &rinfo_;
  }

 private:
  // Advance* moves the position before/after reading.
  // *Read* reads from current byte(s) into rinfo_.
  // *Get* just reads and returns info on current byte.
  void Advance(int bytes = 1) { pos_ -= bytes; }
  int AdvanceGetTag();
  int GetExtraTag();
  int GetTopTag();
  void ReadTaggedPC();
  void AdvanceReadPC();
579
  void AdvanceReadId();
580
  void AdvanceReadConstPoolData();
581
  void AdvanceReadPosition();
582 583
  void AdvanceReadData();
  void AdvanceReadVariableLengthPCJump();
584 585 586
  int GetLocatableTypeTag();
  void ReadTaggedId();
  void ReadTaggedPosition();
587 588 589

  // If the given mode is wanted, set it in rinfo_ and return true.
  // Else return false. Used for efficiently skipping unwanted modes.
590
  bool SetMode(RelocInfo::Mode mode) {
591
    return (mode_mask_ & (1 << mode)) ? (rinfo_.rmode_ = mode, true) : false;
592 593 594 595
  }

  byte* pos_;
  byte* end_;
596
  byte* code_age_sequence_;
597 598 599
  RelocInfo rinfo_;
  bool done_;
  int mode_mask_;
600 601
  int last_id_;
  int last_position_;
602
  DISALLOW_COPY_AND_ASSIGN(RelocIterator);
603 604 605 606 607 608 609 610 611
};


//------------------------------------------------------------------------------
// External function

//----------------------------------------------------------------------------
class IC_Utility;
class SCTableReference;
612 613 614
#ifdef ENABLE_DEBUGGER_SUPPORT
class Debug_Address;
#endif
615

616 617 618 619 620 621

// An ExternalReference represents a C++ address used in the generated
// code. All references to C++ functions and variables must be encapsulated in
// an ExternalReference instance. This is done in order to track the origin of
// all external references in the code so that they can be bound to the correct
// addresses when deserializing a heap.
622 623
class ExternalReference BASE_EMBEDDED {
 public:
624 625
  // Used in the simulator to support different native api calls.
  enum Type {
626 627
    // Builtin call.
    // MaybeObject* f(v8::internal::Arguments).
628
    BUILTIN_CALL,  // default
629

630 631 632 633
    // Builtin that takes float arguments and returns an int.
    // int f(double, double).
    BUILTIN_COMPARE_CALL,

634 635
    // Builtin call that returns floating point.
    // double f(double, double).
636 637 638 639 640 641 642 643 644
    BUILTIN_FP_FP_CALL,

    // Builtin call that returns floating point.
    // double f(double).
    BUILTIN_FP_CALL,

    // Builtin call that returns floating point.
    // double f(double, int).
    BUILTIN_FP_INT_CALL,
645 646 647 648 649

    // Direct call to API function callback.
    // Handle<Value> f(v8::Arguments&)
    DIRECT_API_CALL,

650 651 652 653
    // Direct call to API function callback.
    // void f(v8::Arguments&)
    DIRECT_API_CALL_NEW,

654 655
    // Direct call to accessor getter callback.
    // Handle<value> f(Local<String> property, AccessorInfo& info)
656 657 658 659 660
    DIRECT_GETTER_CALL,

    // Direct call to accessor getter callback.
    // void f(Local<String> property, AccessorInfo& info)
    DIRECT_GETTER_CALL_NEW
661 662
  };

663
  static void SetUp();
664 665
  static void InitializeMathExpData();
  static void TearDownMathExpData();
666

667 668
  typedef void* ExternalReferenceRedirector(void* original, Type type);

669
  ExternalReference(Builtins::CFunctionId id, Isolate* isolate);
670

671
  ExternalReference(ApiFunction* ptr, Type type, Isolate* isolate);
672

673
  ExternalReference(Builtins::Name name, Isolate* isolate);
674

675
  ExternalReference(Runtime::FunctionId id, Isolate* isolate);
676

677
  ExternalReference(const Runtime::Function* f, Isolate* isolate);
678

679
  ExternalReference(const IC_Utility& ic_utility, Isolate* isolate);
680

681
#ifdef ENABLE_DEBUGGER_SUPPORT
682
  ExternalReference(const Debug_Address& debug_address, Isolate* isolate);
683
#endif
684 685 686

  explicit ExternalReference(StatsCounter* counter);

687
  ExternalReference(Isolate::AddressId id, Isolate* isolate);
688 689 690

  explicit ExternalReference(const SCTableReference& table_ref);

691
  // Isolate::Current() as an external reference.
692
  static ExternalReference isolate_address(Isolate* isolate);
693

694 695 696 697
  // One-of-a-kind references. These references are not part of a general
  // pattern. This means that they have to be added to the
  // ExternalReferenceTable in serialize.cc manually.

698 699 700 701 702 703
  static ExternalReference incremental_marking_record_write_function(
      Isolate* isolate);
  static ExternalReference incremental_evacuation_record_write_function(
      Isolate* isolate);
  static ExternalReference store_buffer_overflow_function(
      Isolate* isolate);
704
  static ExternalReference flush_icache_function(Isolate* isolate);
705 706 707 708 709 710
  static ExternalReference perform_gc_function(Isolate* isolate);
  static ExternalReference fill_heap_number_with_random_function(
      Isolate* isolate);
  static ExternalReference random_uint32_function(Isolate* isolate);
  static ExternalReference transcendental_cache_array_address(Isolate* isolate);
  static ExternalReference delete_handle_scope_extensions(Isolate* isolate);
711

712 713 714
  static ExternalReference get_date_field_function(Isolate* isolate);
  static ExternalReference date_cache_stamp(Isolate* isolate);

715 716
  static ExternalReference get_make_code_young_function(Isolate* isolate);

717
  // Deoptimization support.
718 719
  static ExternalReference new_deoptimizer_function(Isolate* isolate);
  static ExternalReference compute_output_frames_function(Isolate* isolate);
720

721 722 723 724
  // Log support.
  static ExternalReference log_enter_external_function(Isolate* isolate);
  static ExternalReference log_leave_external_function(Isolate* isolate);

725
  // Static data in the keyed lookup cache.
726 727
  static ExternalReference keyed_lookup_cache_keys(Isolate* isolate);
  static ExternalReference keyed_lookup_cache_field_offsets(Isolate* isolate);
728

729 730
  // Static variable Heap::roots_array_start()
  static ExternalReference roots_array_start(Isolate* isolate);
731

732
  // Static variable StackGuard::address_of_jslimit()
733
  static ExternalReference address_of_stack_limit(Isolate* isolate);
734 735

  // Static variable StackGuard::address_of_real_jslimit()
736
  static ExternalReference address_of_real_stack_limit(Isolate* isolate);
737

738
  // Static variable RegExpStack::limit_address()
739
  static ExternalReference address_of_regexp_stack_limit(Isolate* isolate);
740

741
  // Static variables for RegExp.
742 743 744 745 746
  static ExternalReference address_of_static_offsets_vector(Isolate* isolate);
  static ExternalReference address_of_regexp_stack_memory_address(
      Isolate* isolate);
  static ExternalReference address_of_regexp_stack_memory_size(
      Isolate* isolate);
747

748
  // Static variable Heap::NewSpaceStart()
749 750 751
  static ExternalReference new_space_start(Isolate* isolate);
  static ExternalReference new_space_mask(Isolate* isolate);
  static ExternalReference heap_always_allocate_scope_depth(Isolate* isolate);
752 753 754 755
  static ExternalReference new_space_mark_bits(Isolate* isolate);

  // Write barrier.
  static ExternalReference store_buffer_top(Isolate* isolate);
756 757

  // Used for fast allocation in generated code.
758 759
  static ExternalReference new_space_allocation_top_address(Isolate* isolate);
  static ExternalReference new_space_allocation_limit_address(Isolate* isolate);
760 761 762 763
  static ExternalReference old_pointer_space_allocation_top_address(
      Isolate* isolate);
  static ExternalReference old_pointer_space_allocation_limit_address(
      Isolate* isolate);
764 765 766 767
  static ExternalReference old_data_space_allocation_top_address(
      Isolate* isolate);
  static ExternalReference old_data_space_allocation_limit_address(
      Isolate* isolate);
768 769
  static ExternalReference new_space_high_promotion_mode_active_address(
      Isolate* isolate);
770

771 772 773 774 775
  static ExternalReference double_fp_operation(Token::Value operation,
                                               Isolate* isolate);
  static ExternalReference compare_doubles(Isolate* isolate);
  static ExternalReference power_double_double_function(Isolate* isolate);
  static ExternalReference power_double_int_function(Isolate* isolate);
776

777 778 779
  static ExternalReference handle_scope_next_address(Isolate* isolate);
  static ExternalReference handle_scope_limit_address(Isolate* isolate);
  static ExternalReference handle_scope_level_address(Isolate* isolate);
780

781
  static ExternalReference scheduled_exception_address(Isolate* isolate);
782 783 784
  static ExternalReference address_of_pending_message_obj(Isolate* isolate);
  static ExternalReference address_of_has_pending_message(Isolate* isolate);
  static ExternalReference address_of_pending_message_script(Isolate* isolate);
785

786 787 788
  // Static variables containing common double constants.
  static ExternalReference address_of_min_int();
  static ExternalReference address_of_one_half();
789
  static ExternalReference address_of_minus_one_half();
790
  static ExternalReference address_of_minus_zero();
791 792
  static ExternalReference address_of_zero();
  static ExternalReference address_of_uint8_max_value();
793
  static ExternalReference address_of_negative_infinity();
794 795
  static ExternalReference address_of_canonical_non_hole_nan();
  static ExternalReference address_of_the_hole_nan();
796

797 798
  static ExternalReference math_sin_double_function(Isolate* isolate);
  static ExternalReference math_cos_double_function(Isolate* isolate);
799
  static ExternalReference math_tan_double_function(Isolate* isolate);
800
  static ExternalReference math_log_double_function(Isolate* isolate);
801

802 803 804
  static ExternalReference math_exp_constants(int constant_index);
  static ExternalReference math_exp_log_table();

805 806
  static ExternalReference page_flags(Page* page);

807 808
  static ExternalReference ForDeoptEntry(Address entry);

809 810
  static ExternalReference cpu_features();

811
  Address address() const {return reinterpret_cast<Address>(address_);}
812

813 814
#ifdef ENABLE_DEBUGGER_SUPPORT
  // Function Debug::Break()
815
  static ExternalReference debug_break(Isolate* isolate);
816 817

  // Used to check if single stepping is enabled in generated code.
818
  static ExternalReference debug_step_in_fp_address(Isolate* isolate);
819 820
#endif

821
#ifndef V8_INTERPRETED_REGEXP
lrn@chromium.org's avatar
lrn@chromium.org committed
822 823 824
  // C functions called from RegExp generated code.

  // Function NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()
825
  static ExternalReference re_case_insensitive_compare_uc16(Isolate* isolate);
lrn@chromium.org's avatar
lrn@chromium.org committed
826 827

  // Function RegExpMacroAssembler*::CheckStackGuardState()
828
  static ExternalReference re_check_stack_guard_state(Isolate* isolate);
lrn@chromium.org's avatar
lrn@chromium.org committed
829 830

  // Function NativeRegExpMacroAssembler::GrowStack()
831
  static ExternalReference re_grow_stack(Isolate* isolate);
832 833 834 835

  // byte NativeRegExpMacroAssembler::word_character_bitmap
  static ExternalReference re_word_character_map();

lrn@chromium.org's avatar
lrn@chromium.org committed
836 837
#endif

838 839
  // This lets you register a function that rewrites all external references.
  // Used by the ARM simulator to catch calls to external references.
840 841
  static void set_redirector(Isolate* isolate,
                             ExternalReferenceRedirector* redirector) {
842
    // We can't stack them.
843 844
    ASSERT(isolate->external_reference_redirector() == NULL);
    isolate->set_external_reference_redirector(
845
        reinterpret_cast<ExternalReferenceRedirectorPointer*>(redirector));
846 847
  }

848 849
 private:
  explicit ExternalReference(void* address)
850 851
      : address_(address) {}

852 853
  static void* Redirect(Isolate* isolate,
                        void* address,
854
                        Type type = ExternalReference::BUILTIN_CALL) {
855 856
    ExternalReferenceRedirector* redirector =
        reinterpret_cast<ExternalReferenceRedirector*>(
857
            isolate->external_reference_redirector());
858 859
    if (redirector == NULL) return address;
    void* answer = (*redirector)(address, type);
860
    return answer;
861 862
  }

863 864
  static void* Redirect(Isolate* isolate,
                        Address address_arg,
865
                        Type type = ExternalReference::BUILTIN_CALL) {
866 867
    ExternalReferenceRedirector* redirector =
        reinterpret_cast<ExternalReferenceRedirector*>(
868
            isolate->external_reference_redirector());
869
    void* address = reinterpret_cast<void*>(address_arg);
870
    void* answer = (redirector == NULL) ?
871
                   address :
872
                   (*redirector)(address, type);
873
    return answer;
874
  }
875

876
  void* address_;
877 878 879
};


880 881 882
// -----------------------------------------------------------------------------
// Position recording support

883 884 885 886 887 888 889 890 891 892 893 894 895
struct PositionState {
  PositionState() : current_position(RelocInfo::kNoPosition),
                    written_position(RelocInfo::kNoPosition),
                    current_statement_position(RelocInfo::kNoPosition),
                    written_statement_position(RelocInfo::kNoPosition) {}

  int current_position;
  int written_position;

  int current_statement_position;
  int written_statement_position;
};

896 897 898 899

class PositionsRecorder BASE_EMBEDDED {
 public:
  explicit PositionsRecorder(Assembler* assembler)
900 901 902 903
      : assembler_(assembler) {
#ifdef ENABLE_GDB_JIT_INTERFACE
    gdbjit_lineinfo_ = NULL;
#endif
904
    jit_handler_data_ = NULL;
905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923
  }

#ifdef ENABLE_GDB_JIT_INTERFACE
  ~PositionsRecorder() {
    delete gdbjit_lineinfo_;
  }

  void StartGDBJITLineInfoRecording() {
    if (FLAG_gdbjit) {
      gdbjit_lineinfo_ = new GDBJITLineInfo();
    }
  }

  GDBJITLineInfo* DetachGDBJITLineInfo() {
    GDBJITLineInfo* lineinfo = gdbjit_lineinfo_;
    gdbjit_lineinfo_ = NULL;  // To prevent deallocation in destructor.
    return lineinfo;
  }
#endif
924 925 926
  void AttachJITHandlerData(void* user_data) {
    jit_handler_data_ = user_data;
  }
927

928 929 930 931 932
  void* DetachJITHandlerData() {
    void* old_data = jit_handler_data_;
    jit_handler_data_ = NULL;
    return old_data;
  }
933 934
  // Set current position to pos.
  void RecordPosition(int pos);
935 936 937 938 939 940 941

  // Set current statement position to pos.
  void RecordStatementPosition(int pos);

  // Write recorded positions to relocation information.
  bool WriteRecordedPositions();

942
  int current_position() const { return state_.current_position; }
943

944 945 946
  int current_statement_position() const {
    return state_.current_statement_position;
  }
947 948 949

 private:
  Assembler* assembler_;
950
  PositionState state_;
951 952 953
#ifdef ENABLE_GDB_JIT_INTERFACE
  GDBJITLineInfo* gdbjit_lineinfo_;
#endif
954

955 956 957
  // Currently jit_handler_data_ is used to store JITHandler-specific data
  // over the lifetime of a PositionsRecorder
  void* jit_handler_data_;
958
  friend class PreservePositionScope;
959

960
  DISALLOW_COPY_AND_ASSIGN(PositionsRecorder);
961 962 963
};


964
class PreservePositionScope BASE_EMBEDDED {
965
 public:
966
  explicit PreservePositionScope(PositionsRecorder* positions_recorder)
967
      : positions_recorder_(positions_recorder),
968
        saved_state_(positions_recorder->state_) {}
969

970 971
  ~PreservePositionScope() {
    positions_recorder_->state_ = saved_state_;
972 973 974 975
  }

 private:
  PositionsRecorder* positions_recorder_;
976 977 978
  const PositionState saved_state_;

  DISALLOW_COPY_AND_ASSIGN(PreservePositionScope);
979 980 981
};


982 983 984
// -----------------------------------------------------------------------------
// Utility functions

985
inline bool is_intn(int x, int n)  {
986 987 988
  return -(1 << (n-1)) <= x && x < (1 << (n-1));
}

989 990 991 992
inline bool is_int8(int x)  { return is_intn(x, 8); }
inline bool is_int16(int x)  { return is_intn(x, 16); }
inline bool is_int18(int x)  { return is_intn(x, 18); }
inline bool is_int24(int x)  { return is_intn(x, 24); }
993

994
inline bool is_uintn(int x, int n) {
995 996 997
  return (x & -(1 << n)) == 0;
}

998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
inline bool is_uint2(int x)  { return is_uintn(x, 2); }
inline bool is_uint3(int x)  { return is_uintn(x, 3); }
inline bool is_uint4(int x)  { return is_uintn(x, 4); }
inline bool is_uint5(int x)  { return is_uintn(x, 5); }
inline bool is_uint6(int x)  { return is_uintn(x, 6); }
inline bool is_uint8(int x)  { return is_uintn(x, 8); }
inline bool is_uint10(int x)  { return is_uintn(x, 10); }
inline bool is_uint12(int x)  { return is_uintn(x, 12); }
inline bool is_uint16(int x)  { return is_uintn(x, 16); }
inline bool is_uint24(int x)  { return is_uintn(x, 24); }
inline bool is_uint26(int x)  { return is_uintn(x, 26); }
inline bool is_uint28(int x)  { return is_uintn(x, 28); }

inline int NumberOfBitsSet(uint32_t x) {
1012 1013 1014 1015 1016 1017
  unsigned int num_bits_set;
  for (num_bits_set = 0; x; x >>= 1) {
    num_bits_set += x & 1;
  }
  return num_bits_set;
}
1018

1019 1020
bool EvalComparison(Token::Value op, double op1, double op2);

1021
// Computes pow(x, y) with the special cases in the spec for Math.pow.
1022
double power_helper(double x, double y);
1023 1024 1025
double power_double_int(double x, int y);
double power_double_double(double x, double y);

1026 1027 1028 1029 1030 1031 1032 1033 1034
// Helper class for generating code or data associated with the code
// right after a call instruction. As an example this can be used to
// generate safepoint data after calls for crankshaft.
class CallWrapper {
 public:
  CallWrapper() { }
  virtual ~CallWrapper() { }
  // Called just before emitting a call. Argument is the size of the generated
  // call code.
1035
  virtual void BeforeCall(int call_size) const = 0;
1036
  // Called just after emitting a call, i.e., at the return site for the call.
1037 1038 1039 1040 1041 1042 1043 1044 1045
  virtual void AfterCall() const = 0;
};

class NullCallWrapper : public CallWrapper {
 public:
  NullCallWrapper() { }
  virtual ~NullCallWrapper() { }
  virtual void BeforeCall(int call_size) const { }
  virtual void AfterCall() const { }
1046 1047
};

1048 1049 1050
} }  // namespace v8::internal

#endif  // V8_ASSEMBLER_H_