1// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// - Redistribution in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// - Neither the name of Sun Microsystems or the names of contributors may
16// be used to endorse or promote products derived from this software without
17// specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// The original source code covered by the above license above has been
32// modified significantly by Google Inc.
33// Copyright 2012 the V8 project authors. All rights reserved.
34
35#ifndef V8_ASSEMBLER_H_
36#define V8_ASSEMBLER_H_
37
38#include "src/v8.h"
39
40#include "src/allocation.h"
41#include "src/builtins.h"
42#include "src/gdb-jit.h"
43#include "src/isolate.h"
44#include "src/runtime.h"
45#include "src/token.h"
46
47namespace v8 {
48
49class ApiFunction;
50
51namespace internal {
52
53class StatsCounter;
54// -----------------------------------------------------------------------------
55// Platform independent assembler base class.
56
57class AssemblerBase: public Malloced {
58 public:
59  AssemblerBase(Isolate* isolate, void* buffer, int buffer_size);
60  virtual ~AssemblerBase();
61
62  Isolate* isolate() const { return isolate_; }
63  int jit_cookie() const { return jit_cookie_; }
64
65  bool emit_debug_code() const { return emit_debug_code_; }
66  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
67
68  bool serializer_enabled() const { return serializer_enabled_; }
69  void enable_serializer() { serializer_enabled_ = true; }
70
71  bool predictable_code_size() const { return predictable_code_size_; }
72  void set_predictable_code_size(bool value) { predictable_code_size_ = value; }
73
74  uint64_t enabled_cpu_features() const { return enabled_cpu_features_; }
75  void set_enabled_cpu_features(uint64_t features) {
76    enabled_cpu_features_ = features;
77  }
78  bool IsEnabled(CpuFeature f) {
79    return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0;
80  }
81
82  // Overwrite a host NaN with a quiet target NaN.  Used by mksnapshot for
83  // cross-snapshotting.
84  static void QuietNaN(HeapObject* nan) { }
85
86  int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
87
88  // This function is called when code generation is aborted, so that
89  // the assembler could clean up internal data structures.
90  virtual void AbortedCodeGeneration() { }
91
92  static const int kMinimalBufferSize = 4*KB;
93
94 protected:
95  // The buffer into which code and relocation info are generated. It could
96  // either be owned by the assembler or be provided externally.
97  byte* buffer_;
98  int buffer_size_;
99  bool own_buffer_;
100
101  // The program counter, which points into the buffer above and moves forward.
102  byte* pc_;
103
104 private:
105  Isolate* isolate_;
106  int jit_cookie_;
107  uint64_t enabled_cpu_features_;
108  bool emit_debug_code_;
109  bool predictable_code_size_;
110  bool serializer_enabled_;
111};
112
113
114// Avoids emitting debug code during the lifetime of this scope object.
115class DontEmitDebugCodeScope BASE_EMBEDDED {
116 public:
117  explicit DontEmitDebugCodeScope(AssemblerBase* assembler)
118      : assembler_(assembler), old_value_(assembler->emit_debug_code()) {
119    assembler_->set_emit_debug_code(false);
120  }
121  ~DontEmitDebugCodeScope() {
122    assembler_->set_emit_debug_code(old_value_);
123  }
124 private:
125  AssemblerBase* assembler_;
126  bool old_value_;
127};
128
129
130// Avoids using instructions that vary in size in unpredictable ways between the
131// snapshot and the running VM.
132class PredictableCodeSizeScope {
133 public:
134  PredictableCodeSizeScope(AssemblerBase* assembler, int expected_size);
135  ~PredictableCodeSizeScope();
136
137 private:
138  AssemblerBase* assembler_;
139  int expected_size_;
140  int start_offset_;
141  bool old_value_;
142};
143
144
145// Enable a specified feature within a scope.
146class CpuFeatureScope BASE_EMBEDDED {
147 public:
148#ifdef DEBUG
149  CpuFeatureScope(AssemblerBase* assembler, CpuFeature f);
150  ~CpuFeatureScope();
151
152 private:
153  AssemblerBase* assembler_;
154  uint64_t old_enabled_;
155#else
156  CpuFeatureScope(AssemblerBase* assembler, CpuFeature f) {}
157#endif
158};
159
160
161// CpuFeatures keeps track of which features are supported by the target CPU.
162// Supported features must be enabled by a CpuFeatureScope before use.
163// Example:
164//   if (assembler->IsSupported(SSE3)) {
165//     CpuFeatureScope fscope(assembler, SSE3);
166//     // Generate code containing SSE3 instructions.
167//   } else {
168//     // Generate alternative code.
169//   }
170class CpuFeatures : public AllStatic {
171 public:
172  static void Probe(bool cross_compile) {
173    STATIC_ASSERT(NUMBER_OF_CPU_FEATURES <= kBitsPerInt);
174    if (initialized_) return;
175    initialized_ = true;
176    ProbeImpl(cross_compile);
177  }
178
179  static unsigned SupportedFeatures() {
180    Probe(false);
181    return supported_;
182  }
183
184  static bool IsSupported(CpuFeature f) {
185    return (supported_ & (1u << f)) != 0;
186  }
187
188  static inline bool SupportsCrankshaft();
189
190  static inline unsigned cache_line_size() {
191    DCHECK(cache_line_size_ != 0);
192    return cache_line_size_;
193  }
194
195  static void PrintTarget();
196  static void PrintFeatures();
197
198  // Flush instruction cache.
199  static void FlushICache(void* start, size_t size);
200
201 private:
202  // Platform-dependent implementation.
203  static void ProbeImpl(bool cross_compile);
204
205  static unsigned supported_;
206  static unsigned cache_line_size_;
207  static bool initialized_;
208  friend class ExternalReference;
209  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
210};
211
212
213// -----------------------------------------------------------------------------
214// Labels represent pc locations; they are typically jump or call targets.
215// After declaration, a label can be freely used to denote known or (yet)
216// unknown pc location. Assembler::bind() is used to bind a label to the
217// current pc. A label can be bound only once.
218
219class Label BASE_EMBEDDED {
220 public:
221  enum Distance {
222    kNear, kFar
223  };
224
225  INLINE(Label()) {
226    Unuse();
227    UnuseNear();
228  }
229
230  INLINE(~Label()) {
231    DCHECK(!is_linked());
232    DCHECK(!is_near_linked());
233  }
234
235  INLINE(void Unuse()) { pos_ = 0; }
236  INLINE(void UnuseNear()) { near_link_pos_ = 0; }
237
238  INLINE(bool is_bound() const) { return pos_ <  0; }
239  INLINE(bool is_unused() const) { return pos_ == 0 && near_link_pos_ == 0; }
240  INLINE(bool is_linked() const) { return pos_ >  0; }
241  INLINE(bool is_near_linked() const) { return near_link_pos_ > 0; }
242
243  // Returns the position of bound or linked labels. Cannot be used
244  // for unused labels.
245  int pos() const;
246  int near_link_pos() const { return near_link_pos_ - 1; }
247
248 private:
249  // pos_ encodes both the binding state (via its sign)
250  // and the binding position (via its value) of a label.
251  //
252  // pos_ <  0  bound label, pos() returns the jump target position
253  // pos_ == 0  unused label
254  // pos_ >  0  linked label, pos() returns the last reference position
255  int pos_;
256
257  // Behaves like |pos_| in the "> 0" case, but for near jumps to this label.
258  int near_link_pos_;
259
260  void bind_to(int pos)  {
261    pos_ = -pos - 1;
262    DCHECK(is_bound());
263  }
264  void link_to(int pos, Distance distance = kFar) {
265    if (distance == kNear) {
266      near_link_pos_ = pos + 1;
267      DCHECK(is_near_linked());
268    } else {
269      pos_ = pos + 1;
270      DCHECK(is_linked());
271    }
272  }
273
274  friend class Assembler;
275  friend class Displacement;
276  friend class RegExpMacroAssemblerIrregexp;
277
278#if V8_TARGET_ARCH_ARM64
279  // On ARM64, the Assembler keeps track of pointers to Labels to resolve
280  // branches to distant targets. Copying labels would confuse the Assembler.
281  DISALLOW_COPY_AND_ASSIGN(Label);  // NOLINT
282#endif
283};
284
285
286enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs };
287
288// Specifies whether to perform icache flush operations on RelocInfo updates.
289// If FLUSH_ICACHE_IF_NEEDED, the icache will always be flushed if an
290// instruction was modified. If SKIP_ICACHE_FLUSH the flush will always be
291// skipped (only use this if you will flush the icache manually before it is
292// executed).
293enum ICacheFlushMode { FLUSH_ICACHE_IF_NEEDED, SKIP_ICACHE_FLUSH };
294
295// -----------------------------------------------------------------------------
296// Relocation information
297
298
299// Relocation information consists of the address (pc) of the datum
300// to which the relocation information applies, the relocation mode
301// (rmode), and an optional data field. The relocation mode may be
302// "descriptive" and not indicate a need for relocation, but simply
303// describe a property of the datum. Such rmodes are useful for GC
304// and nice disassembly output.
305
306class RelocInfo {
307 public:
308  // The constant kNoPosition is used with the collecting of source positions
309  // in the relocation information. Two types of source positions are collected
310  // "position" (RelocMode position) and "statement position" (RelocMode
311  // statement_position). The "position" is collected at places in the source
312  // code which are of interest when making stack traces to pin-point the source
313  // location of a stack frame as close as possible. The "statement position" is
314  // collected at the beginning at each statement, and is used to indicate
315  // possible break locations. kNoPosition is used to indicate an
316  // invalid/uninitialized position value.
317  static const int kNoPosition = -1;
318
319  // This string is used to add padding comments to the reloc info in cases
320  // where we are not sure to have enough space for patching in during
321  // lazy deoptimization. This is the case if we have indirect calls for which
322  // we do not normally record relocation info.
323  static const char* const kFillerCommentString;
324
325  // The minimum size of a comment is equal to three bytes for the extra tagged
326  // pc + the tag for the data, and kPointerSize for the actual pointer to the
327  // comment.
328  static const int kMinRelocCommentSize = 3 + kPointerSize;
329
330  // The maximum size for a call instruction including pc-jump.
331  static const int kMaxCallSize = 6;
332
333  // The maximum pc delta that will use the short encoding.
334  static const int kMaxSmallPCDelta;
335
336  enum Mode {
337    // Please note the order is important (see IsCodeTarget, IsGCRelocMode).
338    CODE_TARGET,  // Code target which is not any of the above.
339    CODE_TARGET_WITH_ID,
340    CONSTRUCT_CALL,  // code target that is a call to a JavaScript constructor.
341    DEBUG_BREAK,  // Code target for the debugger statement.
342    EMBEDDED_OBJECT,
343    CELL,
344
345    // Everything after runtime_entry (inclusive) is not GC'ed.
346    RUNTIME_ENTRY,
347    JS_RETURN,  // Marks start of the ExitJSFrame code.
348    COMMENT,
349    POSITION,  // See comment for kNoPosition above.
350    STATEMENT_POSITION,  // See comment for kNoPosition above.
351    DEBUG_BREAK_SLOT,  // Additional code inserted for debug break slot.
352    EXTERNAL_REFERENCE,  // The address of an external C++ function.
353    INTERNAL_REFERENCE,  // An address inside the same function.
354
355    // Marks constant and veneer pools. Only used on ARM and ARM64.
356    // They use a custom noncompact encoding.
357    CONST_POOL,
358    VENEER_POOL,
359
360    // add more as needed
361    // Pseudo-types
362    NUMBER_OF_MODES,  // There are at most 15 modes with noncompact encoding.
363    NONE32,  // never recorded 32-bit value
364    NONE64,  // never recorded 64-bit value
365    CODE_AGE_SEQUENCE,  // Not stored in RelocInfo array, used explictly by
366                        // code aging.
367    FIRST_REAL_RELOC_MODE = CODE_TARGET,
368    LAST_REAL_RELOC_MODE = VENEER_POOL,
369    FIRST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE,
370    LAST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE,
371    LAST_CODE_ENUM = DEBUG_BREAK,
372    LAST_GCED_ENUM = CELL,
373    // Modes <= LAST_COMPACT_ENUM are guaranteed to have compact encoding.
374    LAST_COMPACT_ENUM = CODE_TARGET_WITH_ID,
375    LAST_STANDARD_NONCOMPACT_ENUM = INTERNAL_REFERENCE
376  };
377
378  RelocInfo() {}
379
380  RelocInfo(byte* pc, Mode rmode, intptr_t data, Code* host)
381      : pc_(pc), rmode_(rmode), data_(data), host_(host) {
382  }
383  RelocInfo(byte* pc, double data64)
384      : pc_(pc), rmode_(NONE64), data64_(data64), host_(NULL) {
385  }
386
387  static inline bool IsRealRelocMode(Mode mode) {
388    return mode >= FIRST_REAL_RELOC_MODE &&
389        mode <= LAST_REAL_RELOC_MODE;
390  }
391  static inline bool IsPseudoRelocMode(Mode mode) {
392    DCHECK(!IsRealRelocMode(mode));
393    return mode >= FIRST_PSEUDO_RELOC_MODE &&
394        mode <= LAST_PSEUDO_RELOC_MODE;
395  }
396  static inline bool IsConstructCall(Mode mode) {
397    return mode == CONSTRUCT_CALL;
398  }
399  static inline bool IsCodeTarget(Mode mode) {
400    return mode <= LAST_CODE_ENUM;
401  }
402  static inline bool IsEmbeddedObject(Mode mode) {
403    return mode == EMBEDDED_OBJECT;
404  }
405  static inline bool IsRuntimeEntry(Mode mode) {
406    return mode == RUNTIME_ENTRY;
407  }
408  // Is the relocation mode affected by GC?
409  static inline bool IsGCRelocMode(Mode mode) {
410    return mode <= LAST_GCED_ENUM;
411  }
412  static inline bool IsJSReturn(Mode mode) {
413    return mode == JS_RETURN;
414  }
415  static inline bool IsComment(Mode mode) {
416    return mode == COMMENT;
417  }
418  static inline bool IsConstPool(Mode mode) {
419    return mode == CONST_POOL;
420  }
421  static inline bool IsVeneerPool(Mode mode) {
422    return mode == VENEER_POOL;
423  }
424  static inline bool IsPosition(Mode mode) {
425    return mode == POSITION || mode == STATEMENT_POSITION;
426  }
427  static inline bool IsStatementPosition(Mode mode) {
428    return mode == STATEMENT_POSITION;
429  }
430  static inline bool IsExternalReference(Mode mode) {
431    return mode == EXTERNAL_REFERENCE;
432  }
433  static inline bool IsInternalReference(Mode mode) {
434    return mode == INTERNAL_REFERENCE;
435  }
436  static inline bool IsDebugBreakSlot(Mode mode) {
437    return mode == DEBUG_BREAK_SLOT;
438  }
439  static inline bool IsNone(Mode mode) {
440    return mode == NONE32 || mode == NONE64;
441  }
442  static inline bool IsCodeAgeSequence(Mode mode) {
443    return mode == CODE_AGE_SEQUENCE;
444  }
445  static inline int ModeMask(Mode mode) { return 1 << mode; }
446
447  // Returns true if the first RelocInfo has the same mode and raw data as the
448  // second one.
449  static inline bool IsEqual(RelocInfo first, RelocInfo second) {
450    return first.rmode() == second.rmode() &&
451           (first.rmode() == RelocInfo::NONE64 ?
452              first.raw_data64() == second.raw_data64() :
453              first.data() == second.data());
454  }
455
456  // Accessors
457  byte* pc() const { return pc_; }
458  void set_pc(byte* pc) { pc_ = pc; }
459  Mode rmode() const {  return rmode_; }
460  intptr_t data() const { return data_; }
461  double data64() const { return data64_; }
462  uint64_t raw_data64() { return bit_cast<uint64_t>(data64_); }
463  Code* host() const { return host_; }
464  void set_host(Code* host) { host_ = host; }
465
466  // Apply a relocation by delta bytes
467  INLINE(void apply(intptr_t delta,
468                    ICacheFlushMode icache_flush_mode =
469                        FLUSH_ICACHE_IF_NEEDED));
470
471  // Is the pointer this relocation info refers to coded like a plain pointer
472  // or is it strange in some way (e.g. relative or patched into a series of
473  // instructions).
474  bool IsCodedSpecially();
475
476  // If true, the pointer this relocation info refers to is an entry in the
477  // constant pool, otherwise the pointer is embedded in the instruction stream.
478  bool IsInConstantPool();
479
480  // Read/modify the code target in the branch/call instruction
481  // this relocation applies to;
482  // can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
483  INLINE(Address target_address());
484  INLINE(void set_target_address(Address target,
485                                 WriteBarrierMode write_barrier_mode =
486                                     UPDATE_WRITE_BARRIER,
487                                 ICacheFlushMode icache_flush_mode =
488                                     FLUSH_ICACHE_IF_NEEDED));
489  INLINE(Object* target_object());
490  INLINE(Handle<Object> target_object_handle(Assembler* origin));
491  INLINE(void set_target_object(Object* target,
492                                WriteBarrierMode write_barrier_mode =
493                                    UPDATE_WRITE_BARRIER,
494                                ICacheFlushMode icache_flush_mode =
495                                    FLUSH_ICACHE_IF_NEEDED));
496  INLINE(Address target_runtime_entry(Assembler* origin));
497  INLINE(void set_target_runtime_entry(Address target,
498                                       WriteBarrierMode write_barrier_mode =
499                                           UPDATE_WRITE_BARRIER,
500                                       ICacheFlushMode icache_flush_mode =
501                                           FLUSH_ICACHE_IF_NEEDED));
502  INLINE(Cell* target_cell());
503  INLINE(Handle<Cell> target_cell_handle());
504  INLINE(void set_target_cell(Cell* cell,
505                              WriteBarrierMode write_barrier_mode =
506                                  UPDATE_WRITE_BARRIER,
507                              ICacheFlushMode icache_flush_mode =
508                                  FLUSH_ICACHE_IF_NEEDED));
509  INLINE(Handle<Object> code_age_stub_handle(Assembler* origin));
510  INLINE(Code* code_age_stub());
511  INLINE(void set_code_age_stub(Code* stub,
512                                ICacheFlushMode icache_flush_mode =
513                                    FLUSH_ICACHE_IF_NEEDED));
514
515  // Returns the address of the constant pool entry where the target address
516  // is held.  This should only be called if IsInConstantPool returns true.
517  INLINE(Address constant_pool_entry_address());
518
519  // Read the address of the word containing the target_address in an
520  // instruction stream.  What this means exactly is architecture-independent.
521  // The only architecture-independent user of this function is the serializer.
522  // The serializer uses it to find out how many raw bytes of instruction to
523  // output before the next target.  Architecture-independent code shouldn't
524  // dereference the pointer it gets back from this.
525  INLINE(Address target_address_address());
526
527  // This indicates how much space a target takes up when deserializing a code
528  // stream.  For most architectures this is just the size of a pointer.  For
529  // an instruction like movw/movt where the target bits are mixed into the
530  // instruction bits the size of the target will be zero, indicating that the
531  // serializer should not step forwards in memory after a target is resolved
532  // and written.  In this case the target_address_address function above
533  // should return the end of the instructions to be patched, allowing the
534  // deserializer to deserialize the instructions as raw bytes and put them in
535  // place, ready to be patched with the target.
536  INLINE(int target_address_size());
537
538  // Read/modify the reference in the instruction this relocation
539  // applies to; can only be called if rmode_ is external_reference
540  INLINE(Address target_reference());
541
542  // Read/modify the address of a call instruction. This is used to relocate
543  // the break points where straight-line code is patched with a call
544  // instruction.
545  INLINE(Address call_address());
546  INLINE(void set_call_address(Address target));
547  INLINE(Object* call_object());
548  INLINE(void set_call_object(Object* target));
549  INLINE(Object** call_object_address());
550
551  // Wipe out a relocation to a fixed value, used for making snapshots
552  // reproducible.
553  INLINE(void WipeOut());
554
555  template<typename StaticVisitor> inline void Visit(Heap* heap);
556  inline void Visit(Isolate* isolate, ObjectVisitor* v);
557
558  // Patch the code with some other code.
559  void PatchCode(byte* instructions, int instruction_count);
560
561  // Patch the code with a call.
562  void PatchCodeWithCall(Address target, int guard_bytes);
563
564  // Check whether this return sequence has been patched
565  // with a call to the debugger.
566  INLINE(bool IsPatchedReturnSequence());
567
568  // Check whether this debug break slot has been patched with a call to the
569  // debugger.
570  INLINE(bool IsPatchedDebugBreakSlotSequence());
571
572#ifdef DEBUG
573  // Check whether the given code contains relocation information that
574  // either is position-relative or movable by the garbage collector.
575  static bool RequiresRelocation(const CodeDesc& desc);
576#endif
577
578#ifdef ENABLE_DISASSEMBLER
579  // Printing
580  static const char* RelocModeName(Mode rmode);
581  void Print(Isolate* isolate, OStream& os);  // NOLINT
582#endif  // ENABLE_DISASSEMBLER
583#ifdef VERIFY_HEAP
584  void Verify(Isolate* isolate);
585#endif
586
587  static const int kCodeTargetMask = (1 << (LAST_CODE_ENUM + 1)) - 1;
588  static const int kPositionMask = 1 << POSITION | 1 << STATEMENT_POSITION;
589  static const int kDataMask =
590      (1 << CODE_TARGET_WITH_ID) | kPositionMask | (1 << COMMENT);
591  static const int kApplyMask;  // Modes affected by apply. Depends on arch.
592
593 private:
594  // On ARM, note that pc_ is the address of the constant pool entry
595  // to be relocated and not the address of the instruction
596  // referencing the constant pool entry (except when rmode_ ==
597  // comment).
598  byte* pc_;
599  Mode rmode_;
600  union {
601    intptr_t data_;
602    double data64_;
603  };
604  Code* host_;
605  // External-reference pointers are also split across instruction-pairs
606  // on some platforms, but are accessed via indirect pointers. This location
607  // provides a place for that pointer to exist naturally. Its address
608  // is returned by RelocInfo::target_reference_address().
609  Address reconstructed_adr_ptr_;
610  friend class RelocIterator;
611};
612
613
614// RelocInfoWriter serializes a stream of relocation info. It writes towards
615// lower addresses.
616class RelocInfoWriter BASE_EMBEDDED {
617 public:
618  RelocInfoWriter() : pos_(NULL),
619                      last_pc_(NULL),
620                      last_id_(0),
621                      last_position_(0) {}
622  RelocInfoWriter(byte* pos, byte* pc) : pos_(pos),
623                                         last_pc_(pc),
624                                         last_id_(0),
625                                         last_position_(0) {}
626
627  byte* pos() const { return pos_; }
628  byte* last_pc() const { return last_pc_; }
629
630  void Write(const RelocInfo* rinfo);
631
632  // Update the state of the stream after reloc info buffer
633  // and/or code is moved while the stream is active.
634  void Reposition(byte* pos, byte* pc) {
635    pos_ = pos;
636    last_pc_ = pc;
637  }
638
639  // Max size (bytes) of a written RelocInfo. Longest encoding is
640  // ExtraTag, VariableLengthPCJump, ExtraTag, pc_delta, ExtraTag, data_delta.
641  // On ia32 and arm this is 1 + 4 + 1 + 1 + 1 + 4 = 12.
642  // On x64 this is 1 + 4 + 1 + 1 + 1 + 8 == 16;
643  // Here we use the maximum of the two.
644  static const int kMaxSize = 16;
645
646 private:
647  inline uint32_t WriteVariableLengthPCJump(uint32_t pc_delta);
648  inline void WriteTaggedPC(uint32_t pc_delta, int tag);
649  inline void WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag);
650  inline void WriteExtraTaggedIntData(int data_delta, int top_tag);
651  inline void WriteExtraTaggedPoolData(int data, int pool_type);
652  inline void WriteExtraTaggedData(intptr_t data_delta, int top_tag);
653  inline void WriteTaggedData(intptr_t data_delta, int tag);
654  inline void WriteExtraTag(int extra_tag, int top_tag);
655
656  byte* pos_;
657  byte* last_pc_;
658  int last_id_;
659  int last_position_;
660  DISALLOW_COPY_AND_ASSIGN(RelocInfoWriter);
661};
662
663
664// A RelocIterator iterates over relocation information.
665// Typical use:
666//
667//   for (RelocIterator it(code); !it.done(); it.next()) {
668//     // do something with it.rinfo() here
669//   }
670//
671// A mask can be specified to skip unwanted modes.
672class RelocIterator: public Malloced {
673 public:
674  // Create a new iterator positioned at
675  // the beginning of the reloc info.
676  // Relocation information with mode k is included in the
677  // iteration iff bit k of mode_mask is set.
678  explicit RelocIterator(Code* code, int mode_mask = -1);
679  explicit RelocIterator(const CodeDesc& desc, int mode_mask = -1);
680
681  // Iteration
682  bool done() const { return done_; }
683  void next();
684
685  // Return pointer valid until next next().
686  RelocInfo* rinfo() {
687    DCHECK(!done());
688    return &rinfo_;
689  }
690
691 private:
692  // Advance* moves the position before/after reading.
693  // *Read* reads from current byte(s) into rinfo_.
694  // *Get* just reads and returns info on current byte.
695  void Advance(int bytes = 1) { pos_ -= bytes; }
696  int AdvanceGetTag();
697  int GetExtraTag();
698  int GetTopTag();
699  void ReadTaggedPC();
700  void AdvanceReadPC();
701  void AdvanceReadId();
702  void AdvanceReadPoolData();
703  void AdvanceReadPosition();
704  void AdvanceReadData();
705  void AdvanceReadVariableLengthPCJump();
706  int GetLocatableTypeTag();
707  void ReadTaggedId();
708  void ReadTaggedPosition();
709
710  // If the given mode is wanted, set it in rinfo_ and return true.
711  // Else return false. Used for efficiently skipping unwanted modes.
712  bool SetMode(RelocInfo::Mode mode) {
713    return (mode_mask_ & (1 << mode)) ? (rinfo_.rmode_ = mode, true) : false;
714  }
715
716  byte* pos_;
717  byte* end_;
718  byte* code_age_sequence_;
719  RelocInfo rinfo_;
720  bool done_;
721  int mode_mask_;
722  int last_id_;
723  int last_position_;
724  DISALLOW_COPY_AND_ASSIGN(RelocIterator);
725};
726
727
728//------------------------------------------------------------------------------
729// External function
730
731//----------------------------------------------------------------------------
732class IC_Utility;
733class SCTableReference;
734class Debug_Address;
735
736
737// An ExternalReference represents a C++ address used in the generated
738// code. All references to C++ functions and variables must be encapsulated in
739// an ExternalReference instance. This is done in order to track the origin of
740// all external references in the code so that they can be bound to the correct
741// addresses when deserializing a heap.
742class ExternalReference BASE_EMBEDDED {
743 public:
744  // Used in the simulator to support different native api calls.
745  enum Type {
746    // Builtin call.
747    // Object* f(v8::internal::Arguments).
748    BUILTIN_CALL,  // default
749
750    // Builtin that takes float arguments and returns an int.
751    // int f(double, double).
752    BUILTIN_COMPARE_CALL,
753
754    // Builtin call that returns floating point.
755    // double f(double, double).
756    BUILTIN_FP_FP_CALL,
757
758    // Builtin call that returns floating point.
759    // double f(double).
760    BUILTIN_FP_CALL,
761
762    // Builtin call that returns floating point.
763    // double f(double, int).
764    BUILTIN_FP_INT_CALL,
765
766    // Direct call to API function callback.
767    // void f(v8::FunctionCallbackInfo&)
768    DIRECT_API_CALL,
769
770    // Call to function callback via InvokeFunctionCallback.
771    // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback)
772    PROFILING_API_CALL,
773
774    // Direct call to accessor getter callback.
775    // void f(Local<Name> property, PropertyCallbackInfo& info)
776    DIRECT_GETTER_CALL,
777
778    // Call to accessor getter callback via InvokeAccessorGetterCallback.
779    // void f(Local<Name> property, PropertyCallbackInfo& info,
780    //     AccessorNameGetterCallback callback)
781    PROFILING_GETTER_CALL
782  };
783
784  static void SetUp();
785  static void InitializeMathExpData();
786  static void TearDownMathExpData();
787
788  typedef void* ExternalReferenceRedirector(void* original, Type type);
789
790  ExternalReference() : address_(NULL) {}
791
792  ExternalReference(Builtins::CFunctionId id, Isolate* isolate);
793
794  ExternalReference(ApiFunction* ptr, Type type, Isolate* isolate);
795
796  ExternalReference(Builtins::Name name, Isolate* isolate);
797
798  ExternalReference(Runtime::FunctionId id, Isolate* isolate);
799
800  ExternalReference(const Runtime::Function* f, Isolate* isolate);
801
802  ExternalReference(const IC_Utility& ic_utility, Isolate* isolate);
803
804  explicit ExternalReference(StatsCounter* counter);
805
806  ExternalReference(Isolate::AddressId id, Isolate* isolate);
807
808  explicit ExternalReference(const SCTableReference& table_ref);
809
810  // Isolate as an external reference.
811  static ExternalReference isolate_address(Isolate* isolate);
812
813  // One-of-a-kind references. These references are not part of a general
814  // pattern. This means that they have to be added to the
815  // ExternalReferenceTable in serialize.cc manually.
816
817  static ExternalReference incremental_marking_record_write_function(
818      Isolate* isolate);
819  static ExternalReference store_buffer_overflow_function(
820      Isolate* isolate);
821  static ExternalReference flush_icache_function(Isolate* isolate);
822  static ExternalReference delete_handle_scope_extensions(Isolate* isolate);
823
824  static ExternalReference get_date_field_function(Isolate* isolate);
825  static ExternalReference date_cache_stamp(Isolate* isolate);
826
827  static ExternalReference get_make_code_young_function(Isolate* isolate);
828  static ExternalReference get_mark_code_as_executed_function(Isolate* isolate);
829
830  // Deoptimization support.
831  static ExternalReference new_deoptimizer_function(Isolate* isolate);
832  static ExternalReference compute_output_frames_function(Isolate* isolate);
833
834  // Log support.
835  static ExternalReference log_enter_external_function(Isolate* isolate);
836  static ExternalReference log_leave_external_function(Isolate* isolate);
837
838  // Static data in the keyed lookup cache.
839  static ExternalReference keyed_lookup_cache_keys(Isolate* isolate);
840  static ExternalReference keyed_lookup_cache_field_offsets(Isolate* isolate);
841
842  // Static variable Heap::roots_array_start()
843  static ExternalReference roots_array_start(Isolate* isolate);
844
845  // Static variable Heap::allocation_sites_list_address()
846  static ExternalReference allocation_sites_list_address(Isolate* isolate);
847
848  // Static variable StackGuard::address_of_jslimit()
849  static ExternalReference address_of_stack_limit(Isolate* isolate);
850
851  // Static variable StackGuard::address_of_real_jslimit()
852  static ExternalReference address_of_real_stack_limit(Isolate* isolate);
853
854  // Static variable RegExpStack::limit_address()
855  static ExternalReference address_of_regexp_stack_limit(Isolate* isolate);
856
857  // Static variables for RegExp.
858  static ExternalReference address_of_static_offsets_vector(Isolate* isolate);
859  static ExternalReference address_of_regexp_stack_memory_address(
860      Isolate* isolate);
861  static ExternalReference address_of_regexp_stack_memory_size(
862      Isolate* isolate);
863
864  // Static variable Heap::NewSpaceStart()
865  static ExternalReference new_space_start(Isolate* isolate);
866  static ExternalReference new_space_mask(Isolate* isolate);
867
868  // Write barrier.
869  static ExternalReference store_buffer_top(Isolate* isolate);
870
871  // Used for fast allocation in generated code.
872  static ExternalReference new_space_allocation_top_address(Isolate* isolate);
873  static ExternalReference new_space_allocation_limit_address(Isolate* isolate);
874  static ExternalReference old_pointer_space_allocation_top_address(
875      Isolate* isolate);
876  static ExternalReference old_pointer_space_allocation_limit_address(
877      Isolate* isolate);
878  static ExternalReference old_data_space_allocation_top_address(
879      Isolate* isolate);
880  static ExternalReference old_data_space_allocation_limit_address(
881      Isolate* isolate);
882
883  static ExternalReference mod_two_doubles_operation(Isolate* isolate);
884  static ExternalReference power_double_double_function(Isolate* isolate);
885  static ExternalReference power_double_int_function(Isolate* isolate);
886
887  static ExternalReference handle_scope_next_address(Isolate* isolate);
888  static ExternalReference handle_scope_limit_address(Isolate* isolate);
889  static ExternalReference handle_scope_level_address(Isolate* isolate);
890
891  static ExternalReference scheduled_exception_address(Isolate* isolate);
892  static ExternalReference address_of_pending_message_obj(Isolate* isolate);
893  static ExternalReference address_of_has_pending_message(Isolate* isolate);
894  static ExternalReference address_of_pending_message_script(Isolate* isolate);
895
896  // Static variables containing common double constants.
897  static ExternalReference address_of_min_int();
898  static ExternalReference address_of_one_half();
899  static ExternalReference address_of_minus_one_half();
900  static ExternalReference address_of_negative_infinity();
901  static ExternalReference address_of_canonical_non_hole_nan();
902  static ExternalReference address_of_the_hole_nan();
903  static ExternalReference address_of_uint32_bias();
904
905  static ExternalReference math_log_double_function(Isolate* isolate);
906
907  static ExternalReference math_exp_constants(int constant_index);
908  static ExternalReference math_exp_log_table();
909
910  static ExternalReference page_flags(Page* page);
911
912  static ExternalReference ForDeoptEntry(Address entry);
913
914  static ExternalReference cpu_features();
915
916  static ExternalReference debug_is_active_address(Isolate* isolate);
917  static ExternalReference debug_after_break_target_address(Isolate* isolate);
918  static ExternalReference debug_restarter_frame_function_pointer_address(
919      Isolate* isolate);
920
921  static ExternalReference is_profiling_address(Isolate* isolate);
922  static ExternalReference invoke_function_callback(Isolate* isolate);
923  static ExternalReference invoke_accessor_getter_callback(Isolate* isolate);
924
925  Address address() const { return reinterpret_cast<Address>(address_); }
926
927  // Function Debug::Break()
928  static ExternalReference debug_break(Isolate* isolate);
929
930  // Used to check if single stepping is enabled in generated code.
931  static ExternalReference debug_step_in_fp_address(Isolate* isolate);
932
933#ifndef V8_INTERPRETED_REGEXP
934  // C functions called from RegExp generated code.
935
936  // Function NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()
937  static ExternalReference re_case_insensitive_compare_uc16(Isolate* isolate);
938
939  // Function RegExpMacroAssembler*::CheckStackGuardState()
940  static ExternalReference re_check_stack_guard_state(Isolate* isolate);
941
942  // Function NativeRegExpMacroAssembler::GrowStack()
943  static ExternalReference re_grow_stack(Isolate* isolate);
944
945  // byte NativeRegExpMacroAssembler::word_character_bitmap
946  static ExternalReference re_word_character_map();
947
948#endif
949
950  // This lets you register a function that rewrites all external references.
951  // Used by the ARM simulator to catch calls to external references.
952  static void set_redirector(Isolate* isolate,
953                             ExternalReferenceRedirector* redirector) {
954    // We can't stack them.
955    DCHECK(isolate->external_reference_redirector() == NULL);
956    isolate->set_external_reference_redirector(
957        reinterpret_cast<ExternalReferenceRedirectorPointer*>(redirector));
958  }
959
960  static ExternalReference stress_deopt_count(Isolate* isolate);
961
962  bool operator==(const ExternalReference& other) const {
963    return address_ == other.address_;
964  }
965
966  bool operator!=(const ExternalReference& other) const {
967    return !(*this == other);
968  }
969
970 private:
971  explicit ExternalReference(void* address)
972      : address_(address) {}
973
974  static void* Redirect(Isolate* isolate,
975                        Address address_arg,
976                        Type type = ExternalReference::BUILTIN_CALL) {
977    ExternalReferenceRedirector* redirector =
978        reinterpret_cast<ExternalReferenceRedirector*>(
979            isolate->external_reference_redirector());
980    void* address = reinterpret_cast<void*>(address_arg);
981    void* answer = (redirector == NULL) ?
982                   address :
983                   (*redirector)(address, type);
984    return answer;
985  }
986
987  void* address_;
988};
989
990
991// -----------------------------------------------------------------------------
992// Position recording support
993
994struct PositionState {
995  PositionState() : current_position(RelocInfo::kNoPosition),
996                    written_position(RelocInfo::kNoPosition),
997                    current_statement_position(RelocInfo::kNoPosition),
998                    written_statement_position(RelocInfo::kNoPosition) {}
999
1000  int current_position;
1001  int written_position;
1002
1003  int current_statement_position;
1004  int written_statement_position;
1005};
1006
1007
1008class PositionsRecorder BASE_EMBEDDED {
1009 public:
1010  explicit PositionsRecorder(Assembler* assembler)
1011      : assembler_(assembler) {
1012    jit_handler_data_ = NULL;
1013  }
1014
1015  void AttachJITHandlerData(void* user_data) {
1016    jit_handler_data_ = user_data;
1017  }
1018
1019  void* DetachJITHandlerData() {
1020    void* old_data = jit_handler_data_;
1021    jit_handler_data_ = NULL;
1022    return old_data;
1023  }
1024  // Set current position to pos.
1025  void RecordPosition(int pos);
1026
1027  // Set current statement position to pos.
1028  void RecordStatementPosition(int pos);
1029
1030  // Write recorded positions to relocation information.
1031  bool WriteRecordedPositions();
1032
1033  int current_position() const { return state_.current_position; }
1034
1035  int current_statement_position() const {
1036    return state_.current_statement_position;
1037  }
1038
1039 private:
1040  Assembler* assembler_;
1041  PositionState state_;
1042
1043  // Currently jit_handler_data_ is used to store JITHandler-specific data
1044  // over the lifetime of a PositionsRecorder
1045  void* jit_handler_data_;
1046  friend class PreservePositionScope;
1047
1048  DISALLOW_COPY_AND_ASSIGN(PositionsRecorder);
1049};
1050
1051
1052class PreservePositionScope BASE_EMBEDDED {
1053 public:
1054  explicit PreservePositionScope(PositionsRecorder* positions_recorder)
1055      : positions_recorder_(positions_recorder),
1056        saved_state_(positions_recorder->state_) {}
1057
1058  ~PreservePositionScope() {
1059    positions_recorder_->state_ = saved_state_;
1060  }
1061
1062 private:
1063  PositionsRecorder* positions_recorder_;
1064  const PositionState saved_state_;
1065
1066  DISALLOW_COPY_AND_ASSIGN(PreservePositionScope);
1067};
1068
1069
1070// -----------------------------------------------------------------------------
1071// Utility functions
1072
1073inline int NumberOfBitsSet(uint32_t x) {
1074  unsigned int num_bits_set;
1075  for (num_bits_set = 0; x; x >>= 1) {
1076    num_bits_set += x & 1;
1077  }
1078  return num_bits_set;
1079}
1080
1081bool EvalComparison(Token::Value op, double op1, double op2);
1082
1083// Computes pow(x, y) with the special cases in the spec for Math.pow.
1084double power_helper(double x, double y);
1085double power_double_int(double x, int y);
1086double power_double_double(double x, double y);
1087
1088// Helper class for generating code or data associated with the code
1089// right after a call instruction. As an example this can be used to
1090// generate safepoint data after calls for crankshaft.
1091class CallWrapper {
1092 public:
1093  CallWrapper() { }
1094  virtual ~CallWrapper() { }
1095  // Called just before emitting a call. Argument is the size of the generated
1096  // call code.
1097  virtual void BeforeCall(int call_size) const = 0;
1098  // Called just after emitting a call, i.e., at the return site for the call.
1099  virtual void AfterCall() const = 0;
1100};
1101
1102class NullCallWrapper : public CallWrapper {
1103 public:
1104  NullCallWrapper() { }
1105  virtual ~NullCallWrapper() { }
1106  virtual void BeforeCall(int call_size) const { }
1107  virtual void AfterCall() const { }
1108};
1109
1110
1111} }  // namespace v8::internal
1112
1113#endif  // V8_ASSEMBLER_H_
1114