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/allocation.h"
39#include "src/builtins/builtins.h"
40#include "src/deoptimize-reason.h"
41#include "src/globals.h"
42#include "src/isolate.h"
43#include "src/label.h"
44#include "src/log.h"
45#include "src/register-configuration.h"
46#include "src/runtime/runtime.h"
47
48namespace v8 {
49
50// Forward declarations.
51class ApiFunction;
52
53namespace internal {
54
55// Forward declarations.
56class SourcePosition;
57class StatsCounter;
58
59// -----------------------------------------------------------------------------
60// Platform independent assembler base class.
61
62enum class CodeObjectRequired { kNo, kYes };
63
64
65class AssemblerBase: public Malloced {
66 public:
67  AssemblerBase(Isolate* isolate, void* buffer, int buffer_size);
68  virtual ~AssemblerBase();
69
70  Isolate* isolate() const { return isolate_; }
71  int jit_cookie() const { return jit_cookie_; }
72
73  bool emit_debug_code() const { return emit_debug_code_; }
74  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
75
76  bool serializer_enabled() const { return serializer_enabled_; }
77  void enable_serializer() { serializer_enabled_ = true; }
78
79  bool predictable_code_size() const { return predictable_code_size_; }
80  void set_predictable_code_size(bool value) { predictable_code_size_ = value; }
81
82  uint64_t enabled_cpu_features() const { return enabled_cpu_features_; }
83  void set_enabled_cpu_features(uint64_t features) {
84    enabled_cpu_features_ = features;
85  }
86  // Features are usually enabled by CpuFeatureScope, which also asserts that
87  // the features are supported before they are enabled.
88  bool IsEnabled(CpuFeature f) {
89    return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0;
90  }
91  void EnableCpuFeature(CpuFeature f) {
92    enabled_cpu_features_ |= (static_cast<uint64_t>(1) << f);
93  }
94
95  bool is_constant_pool_available() const {
96    if (FLAG_enable_embedded_constant_pool) {
97      return constant_pool_available_;
98    } else {
99      // Embedded constant pool not supported on this architecture.
100      UNREACHABLE();
101      return false;
102    }
103  }
104
105  // Overwrite a host NaN with a quiet target NaN.  Used by mksnapshot for
106  // cross-snapshotting.
107  static void QuietNaN(HeapObject* nan) { }
108
109  int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
110
111  // This function is called when code generation is aborted, so that
112  // the assembler could clean up internal data structures.
113  virtual void AbortedCodeGeneration() { }
114
115  // Debugging
116  void Print();
117
118  static const int kMinimalBufferSize = 4*KB;
119
120  static void FlushICache(Isolate* isolate, void* start, size_t size);
121
122 protected:
123  // The buffer into which code and relocation info are generated. It could
124  // either be owned by the assembler or be provided externally.
125  byte* buffer_;
126  int buffer_size_;
127  bool own_buffer_;
128
129  void set_constant_pool_available(bool available) {
130    if (FLAG_enable_embedded_constant_pool) {
131      constant_pool_available_ = available;
132    } else {
133      // Embedded constant pool not supported on this architecture.
134      UNREACHABLE();
135    }
136  }
137
138  // The program counter, which points into the buffer above and moves forward.
139  byte* pc_;
140
141 private:
142  Isolate* isolate_;
143  int jit_cookie_;
144  uint64_t enabled_cpu_features_;
145  bool emit_debug_code_;
146  bool predictable_code_size_;
147  bool serializer_enabled_;
148
149  // Indicates whether the constant pool can be accessed, which is only possible
150  // if the pp register points to the current code object's constant pool.
151  bool constant_pool_available_;
152
153  // Constant pool.
154  friend class FrameAndConstantPoolScope;
155  friend class ConstantPoolUnavailableScope;
156};
157
158
159// Avoids emitting debug code during the lifetime of this scope object.
160class DontEmitDebugCodeScope BASE_EMBEDDED {
161 public:
162  explicit DontEmitDebugCodeScope(AssemblerBase* assembler)
163      : assembler_(assembler), old_value_(assembler->emit_debug_code()) {
164    assembler_->set_emit_debug_code(false);
165  }
166  ~DontEmitDebugCodeScope() {
167    assembler_->set_emit_debug_code(old_value_);
168  }
169 private:
170  AssemblerBase* assembler_;
171  bool old_value_;
172};
173
174
175// Avoids using instructions that vary in size in unpredictable ways between the
176// snapshot and the running VM.
177class PredictableCodeSizeScope {
178 public:
179  explicit PredictableCodeSizeScope(AssemblerBase* assembler);
180  PredictableCodeSizeScope(AssemblerBase* assembler, int expected_size);
181  ~PredictableCodeSizeScope();
182  void ExpectSize(int expected_size) { expected_size_ = expected_size; }
183
184 private:
185  AssemblerBase* assembler_;
186  int expected_size_;
187  int start_offset_;
188  bool old_value_;
189};
190
191
192// Enable a specified feature within a scope.
193class CpuFeatureScope BASE_EMBEDDED {
194 public:
195  enum CheckPolicy {
196    kCheckSupported,
197    kDontCheckSupported,
198  };
199
200#ifdef DEBUG
201  CpuFeatureScope(AssemblerBase* assembler, CpuFeature f,
202                  CheckPolicy check = kCheckSupported);
203  ~CpuFeatureScope();
204
205 private:
206  AssemblerBase* assembler_;
207  uint64_t old_enabled_;
208#else
209  CpuFeatureScope(AssemblerBase* assembler, CpuFeature f,
210                  CheckPolicy check = kCheckSupported) {}
211#endif
212};
213
214
215// CpuFeatures keeps track of which features are supported by the target CPU.
216// Supported features must be enabled by a CpuFeatureScope before use.
217// Example:
218//   if (assembler->IsSupported(SSE3)) {
219//     CpuFeatureScope fscope(assembler, SSE3);
220//     // Generate code containing SSE3 instructions.
221//   } else {
222//     // Generate alternative code.
223//   }
224class CpuFeatures : public AllStatic {
225 public:
226  static void Probe(bool cross_compile) {
227    STATIC_ASSERT(NUMBER_OF_CPU_FEATURES <= kBitsPerInt);
228    if (initialized_) return;
229    initialized_ = true;
230    ProbeImpl(cross_compile);
231  }
232
233  static unsigned SupportedFeatures() {
234    Probe(false);
235    return supported_;
236  }
237
238  static bool IsSupported(CpuFeature f) {
239    return (supported_ & (1u << f)) != 0;
240  }
241
242  static inline bool SupportsCrankshaft();
243
244  static inline bool SupportsSimd128();
245
246  static inline unsigned icache_line_size() {
247    DCHECK(icache_line_size_ != 0);
248    return icache_line_size_;
249  }
250
251  static inline unsigned dcache_line_size() {
252    DCHECK(dcache_line_size_ != 0);
253    return dcache_line_size_;
254  }
255
256  static void PrintTarget();
257  static void PrintFeatures();
258
259 private:
260  friend class ExternalReference;
261  friend class AssemblerBase;
262  // Flush instruction cache.
263  static void FlushICache(void* start, size_t size);
264
265  // Platform-dependent implementation.
266  static void ProbeImpl(bool cross_compile);
267
268  static unsigned supported_;
269  static unsigned icache_line_size_;
270  static unsigned dcache_line_size_;
271  static bool initialized_;
272  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
273};
274
275
276enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs };
277
278enum ArgvMode { kArgvOnStack, kArgvInRegister };
279
280// Specifies whether to perform icache flush operations on RelocInfo updates.
281// If FLUSH_ICACHE_IF_NEEDED, the icache will always be flushed if an
282// instruction was modified. If SKIP_ICACHE_FLUSH the flush will always be
283// skipped (only use this if you will flush the icache manually before it is
284// executed).
285enum ICacheFlushMode { FLUSH_ICACHE_IF_NEEDED, SKIP_ICACHE_FLUSH };
286
287// -----------------------------------------------------------------------------
288// Relocation information
289
290
291// Relocation information consists of the address (pc) of the datum
292// to which the relocation information applies, the relocation mode
293// (rmode), and an optional data field. The relocation mode may be
294// "descriptive" and not indicate a need for relocation, but simply
295// describe a property of the datum. Such rmodes are useful for GC
296// and nice disassembly output.
297
298class RelocInfo {
299 public:
300  // This string is used to add padding comments to the reloc info in cases
301  // where we are not sure to have enough space for patching in during
302  // lazy deoptimization. This is the case if we have indirect calls for which
303  // we do not normally record relocation info.
304  static const char* const kFillerCommentString;
305
306  // The minimum size of a comment is equal to two bytes for the extra tagged
307  // pc and kPointerSize for the actual pointer to the comment.
308  static const int kMinRelocCommentSize = 2 + kPointerSize;
309
310  // The maximum size for a call instruction including pc-jump.
311  static const int kMaxCallSize = 6;
312
313  // The maximum pc delta that will use the short encoding.
314  static const int kMaxSmallPCDelta;
315
316  enum Mode {
317    // Please note the order is important (see IsCodeTarget, IsGCRelocMode).
318    CODE_TARGET,  // Code target which is not any of the above.
319    CODE_TARGET_WITH_ID,
320    EMBEDDED_OBJECT,
321    // To relocate pointers into the wasm memory embedded in wasm code
322    WASM_MEMORY_REFERENCE,
323    WASM_GLOBAL_REFERENCE,
324    WASM_MEMORY_SIZE_REFERENCE,
325    WASM_FUNCTION_TABLE_SIZE_REFERENCE,
326    WASM_PROTECTED_INSTRUCTION_LANDING,
327    CELL,
328
329    // Everything after runtime_entry (inclusive) is not GC'ed.
330    RUNTIME_ENTRY,
331    COMMENT,
332
333    // Additional code inserted for debug break slot.
334    DEBUG_BREAK_SLOT_AT_POSITION,
335    DEBUG_BREAK_SLOT_AT_RETURN,
336    DEBUG_BREAK_SLOT_AT_CALL,
337    DEBUG_BREAK_SLOT_AT_TAIL_CALL,
338
339    EXTERNAL_REFERENCE,  // The address of an external C++ function.
340    INTERNAL_REFERENCE,  // An address inside the same function.
341
342    // Encoded internal reference, used only on MIPS, MIPS64 and PPC.
343    INTERNAL_REFERENCE_ENCODED,
344
345    // Marks constant and veneer pools. Only used on ARM and ARM64.
346    // They use a custom noncompact encoding.
347    CONST_POOL,
348    VENEER_POOL,
349
350    DEOPT_SCRIPT_OFFSET,
351    DEOPT_INLINING_ID,  // Deoptimization source position.
352    DEOPT_REASON,       // Deoptimization reason index.
353    DEOPT_ID,           // Deoptimization inlining id.
354
355    // This is not an actual reloc mode, but used to encode a long pc jump that
356    // cannot be encoded as part of another record.
357    PC_JUMP,
358
359    // Pseudo-types
360    NUMBER_OF_MODES,
361    NONE32,             // never recorded 32-bit value
362    NONE64,             // never recorded 64-bit value
363    CODE_AGE_SEQUENCE,  // Not stored in RelocInfo array, used explictly by
364                        // code aging.
365
366    FIRST_REAL_RELOC_MODE = CODE_TARGET,
367    LAST_REAL_RELOC_MODE = VENEER_POOL,
368    LAST_CODE_ENUM = CODE_TARGET_WITH_ID,
369    LAST_GCED_ENUM = WASM_FUNCTION_TABLE_SIZE_REFERENCE,
370    FIRST_SHAREABLE_RELOC_MODE = CELL,
371  };
372
373  STATIC_ASSERT(NUMBER_OF_MODES <= kBitsPerInt);
374
375  explicit RelocInfo(Isolate* isolate) : isolate_(isolate) {
376    DCHECK_NOT_NULL(isolate);
377  }
378
379  RelocInfo(Isolate* isolate, byte* pc, Mode rmode, intptr_t data, Code* host)
380      : isolate_(isolate), pc_(pc), rmode_(rmode), data_(data), host_(host) {
381    DCHECK_NOT_NULL(isolate);
382  }
383
384  static inline bool IsRealRelocMode(Mode mode) {
385    return mode >= FIRST_REAL_RELOC_MODE && mode <= LAST_REAL_RELOC_MODE;
386  }
387  static inline bool IsCodeTarget(Mode mode) {
388    return mode <= LAST_CODE_ENUM;
389  }
390  static inline bool IsEmbeddedObject(Mode mode) {
391    return mode == EMBEDDED_OBJECT;
392  }
393  static inline bool IsCell(Mode mode) { return mode == CELL; }
394  static inline bool IsRuntimeEntry(Mode mode) {
395    return mode == RUNTIME_ENTRY;
396  }
397  // Is the relocation mode affected by GC?
398  static inline bool IsGCRelocMode(Mode mode) {
399    return mode <= LAST_GCED_ENUM;
400  }
401  static inline bool IsComment(Mode mode) {
402    return mode == COMMENT;
403  }
404  static inline bool IsConstPool(Mode mode) {
405    return mode == CONST_POOL;
406  }
407  static inline bool IsVeneerPool(Mode mode) {
408    return mode == VENEER_POOL;
409  }
410  static inline bool IsDeoptPosition(Mode mode) {
411    return mode == DEOPT_SCRIPT_OFFSET || mode == DEOPT_INLINING_ID;
412  }
413  static inline bool IsDeoptReason(Mode mode) {
414    return mode == DEOPT_REASON;
415  }
416  static inline bool IsDeoptId(Mode mode) {
417    return mode == DEOPT_ID;
418  }
419  static inline bool IsExternalReference(Mode mode) {
420    return mode == EXTERNAL_REFERENCE;
421  }
422  static inline bool IsInternalReference(Mode mode) {
423    return mode == INTERNAL_REFERENCE;
424  }
425  static inline bool IsInternalReferenceEncoded(Mode mode) {
426    return mode == INTERNAL_REFERENCE_ENCODED;
427  }
428  static inline bool IsDebugBreakSlot(Mode mode) {
429    return IsDebugBreakSlotAtPosition(mode) || IsDebugBreakSlotAtReturn(mode) ||
430           IsDebugBreakSlotAtCall(mode) || IsDebugBreakSlotAtTailCall(mode);
431  }
432  static inline bool IsDebugBreakSlotAtPosition(Mode mode) {
433    return mode == DEBUG_BREAK_SLOT_AT_POSITION;
434  }
435  static inline bool IsDebugBreakSlotAtReturn(Mode mode) {
436    return mode == DEBUG_BREAK_SLOT_AT_RETURN;
437  }
438  static inline bool IsDebugBreakSlotAtCall(Mode mode) {
439    return mode == DEBUG_BREAK_SLOT_AT_CALL;
440  }
441  static inline bool IsDebugBreakSlotAtTailCall(Mode mode) {
442    return mode == DEBUG_BREAK_SLOT_AT_TAIL_CALL;
443  }
444  static inline bool IsNone(Mode mode) {
445    return mode == NONE32 || mode == NONE64;
446  }
447  static inline bool IsCodeAgeSequence(Mode mode) {
448    return mode == CODE_AGE_SEQUENCE;
449  }
450  static inline bool IsWasmMemoryReference(Mode mode) {
451    return mode == WASM_MEMORY_REFERENCE;
452  }
453  static inline bool IsWasmMemorySizeReference(Mode mode) {
454    return mode == WASM_MEMORY_SIZE_REFERENCE;
455  }
456  static inline bool IsWasmGlobalReference(Mode mode) {
457    return mode == WASM_GLOBAL_REFERENCE;
458  }
459  static inline bool IsWasmFunctionTableSizeReference(Mode mode) {
460    return mode == WASM_FUNCTION_TABLE_SIZE_REFERENCE;
461  }
462  static inline bool IsWasmReference(Mode mode) {
463    return mode == WASM_MEMORY_REFERENCE || mode == WASM_GLOBAL_REFERENCE ||
464           mode == WASM_MEMORY_SIZE_REFERENCE ||
465           mode == WASM_FUNCTION_TABLE_SIZE_REFERENCE;
466  }
467  static inline bool IsWasmSizeReference(Mode mode) {
468    return mode == WASM_MEMORY_SIZE_REFERENCE ||
469           mode == WASM_FUNCTION_TABLE_SIZE_REFERENCE;
470  }
471  static inline bool IsWasmPtrReference(Mode mode) {
472    return mode == WASM_MEMORY_REFERENCE || mode == WASM_GLOBAL_REFERENCE;
473  }
474  static inline bool IsWasmProtectedLanding(Mode mode) {
475    return mode == WASM_PROTECTED_INSTRUCTION_LANDING;
476  }
477
478  static inline int ModeMask(Mode mode) { return 1 << mode; }
479
480  // Accessors
481  Isolate* isolate() const { return isolate_; }
482  byte* pc() const { return pc_; }
483  void set_pc(byte* pc) { pc_ = pc; }
484  Mode rmode() const {  return rmode_; }
485  intptr_t data() const { return data_; }
486  Code* host() const { return host_; }
487  void set_host(Code* host) { host_ = host; }
488
489  // Apply a relocation by delta bytes. When the code object is moved, PC
490  // relative addresses have to be updated as well as absolute addresses
491  // inside the code (internal references).
492  // Do not forget to flush the icache afterwards!
493  INLINE(void apply(intptr_t delta));
494
495  // Is the pointer this relocation info refers to coded like a plain pointer
496  // or is it strange in some way (e.g. relative or patched into a series of
497  // instructions).
498  bool IsCodedSpecially();
499
500  // If true, the pointer this relocation info refers to is an entry in the
501  // constant pool, otherwise the pointer is embedded in the instruction stream.
502  bool IsInConstantPool();
503
504  Address wasm_memory_reference();
505  Address wasm_global_reference();
506  uint32_t wasm_function_table_size_reference();
507  uint32_t wasm_memory_size_reference();
508  void update_wasm_memory_reference(
509      Address old_base, Address new_base,
510      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
511  void update_wasm_memory_size(
512      uint32_t old_size, uint32_t new_size,
513      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
514  void update_wasm_global_reference(
515      Address old_base, Address new_base,
516      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
517  void update_wasm_function_table_size_reference(
518      uint32_t old_base, uint32_t new_base,
519      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
520  void set_target_address(
521      Address target,
522      WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
523      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
524
525  // this relocation applies to;
526  // can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
527  INLINE(Address target_address());
528  INLINE(Object* target_object());
529  INLINE(Handle<Object> target_object_handle(Assembler* origin));
530  INLINE(void set_target_object(
531      Object* target,
532      WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
533      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
534  INLINE(Address target_runtime_entry(Assembler* origin));
535  INLINE(void set_target_runtime_entry(
536      Address target,
537      WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
538      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
539  INLINE(Cell* target_cell());
540  INLINE(Handle<Cell> target_cell_handle());
541  INLINE(void set_target_cell(
542      Cell* cell, WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
543      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
544  INLINE(Handle<Object> code_age_stub_handle(Assembler* origin));
545  INLINE(Code* code_age_stub());
546  INLINE(void set_code_age_stub(
547      Code* stub, ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
548
549  // Returns the address of the constant pool entry where the target address
550  // is held.  This should only be called if IsInConstantPool returns true.
551  INLINE(Address constant_pool_entry_address());
552
553  // Read the address of the word containing the target_address in an
554  // instruction stream.  What this means exactly is architecture-independent.
555  // The only architecture-independent user of this function is the serializer.
556  // The serializer uses it to find out how many raw bytes of instruction to
557  // output before the next target.  Architecture-independent code shouldn't
558  // dereference the pointer it gets back from this.
559  INLINE(Address target_address_address());
560
561  // This indicates how much space a target takes up when deserializing a code
562  // stream.  For most architectures this is just the size of a pointer.  For
563  // an instruction like movw/movt where the target bits are mixed into the
564  // instruction bits the size of the target will be zero, indicating that the
565  // serializer should not step forwards in memory after a target is resolved
566  // and written.  In this case the target_address_address function above
567  // should return the end of the instructions to be patched, allowing the
568  // deserializer to deserialize the instructions as raw bytes and put them in
569  // place, ready to be patched with the target.
570  INLINE(int target_address_size());
571
572  // Read the reference in the instruction this relocation
573  // applies to; can only be called if rmode_ is EXTERNAL_REFERENCE.
574  INLINE(Address target_external_reference());
575
576  // Read the reference in the instruction this relocation
577  // applies to; can only be called if rmode_ is INTERNAL_REFERENCE.
578  INLINE(Address target_internal_reference());
579
580  // Return the reference address this relocation applies to;
581  // can only be called if rmode_ is INTERNAL_REFERENCE.
582  INLINE(Address target_internal_reference_address());
583
584  // Read/modify the address of a call instruction. This is used to relocate
585  // the break points where straight-line code is patched with a call
586  // instruction.
587  INLINE(Address debug_call_address());
588  INLINE(void set_debug_call_address(Address target));
589
590  // Wipe out a relocation to a fixed value, used for making snapshots
591  // reproducible.
592  INLINE(void WipeOut());
593
594  template<typename StaticVisitor> inline void Visit(Heap* heap);
595
596  template <typename ObjectVisitor>
597  inline void Visit(Isolate* isolate, ObjectVisitor* v);
598
599  // Check whether this debug break slot has been patched with a call to the
600  // debugger.
601  bool IsPatchedDebugBreakSlotSequence();
602
603#ifdef DEBUG
604  // Check whether the given code contains relocation information that
605  // either is position-relative or movable by the garbage collector.
606  static bool RequiresRelocation(const CodeDesc& desc);
607#endif
608
609#ifdef ENABLE_DISASSEMBLER
610  // Printing
611  static const char* RelocModeName(Mode rmode);
612  void Print(Isolate* isolate, std::ostream& os);  // NOLINT
613#endif  // ENABLE_DISASSEMBLER
614#ifdef VERIFY_HEAP
615  void Verify(Isolate* isolate);
616#endif
617
618  static const int kCodeTargetMask = (1 << (LAST_CODE_ENUM + 1)) - 1;
619  static const int kDataMask = (1 << CODE_TARGET_WITH_ID) | (1 << COMMENT);
620  static const int kDebugBreakSlotMask = 1 << DEBUG_BREAK_SLOT_AT_POSITION |
621                                         1 << DEBUG_BREAK_SLOT_AT_RETURN |
622                                         1 << DEBUG_BREAK_SLOT_AT_CALL;
623  static const int kApplyMask;  // Modes affected by apply.  Depends on arch.
624
625 private:
626  void unchecked_update_wasm_memory_reference(Address address,
627                                              ICacheFlushMode flush_mode);
628  void unchecked_update_wasm_size(uint32_t size, ICacheFlushMode flush_mode);
629
630  Isolate* isolate_;
631  // On ARM, note that pc_ is the address of the constant pool entry
632  // to be relocated and not the address of the instruction
633  // referencing the constant pool entry (except when rmode_ ==
634  // comment).
635  byte* pc_;
636  Mode rmode_;
637  intptr_t data_;
638  Code* host_;
639  friend class RelocIterator;
640};
641
642
643// RelocInfoWriter serializes a stream of relocation info. It writes towards
644// lower addresses.
645class RelocInfoWriter BASE_EMBEDDED {
646 public:
647  RelocInfoWriter() : pos_(NULL), last_pc_(NULL), last_id_(0) {}
648  RelocInfoWriter(byte* pos, byte* pc) : pos_(pos), last_pc_(pc), last_id_(0) {}
649
650  byte* pos() const { return pos_; }
651  byte* last_pc() const { return last_pc_; }
652
653  void Write(const RelocInfo* rinfo);
654
655  // Update the state of the stream after reloc info buffer
656  // and/or code is moved while the stream is active.
657  void Reposition(byte* pos, byte* pc) {
658    pos_ = pos;
659    last_pc_ = pc;
660  }
661
662  // Max size (bytes) of a written RelocInfo. Longest encoding is
663  // ExtraTag, VariableLengthPCJump, ExtraTag, pc_delta, data_delta.
664  // On ia32 and arm this is 1 + 4 + 1 + 1 + 4 = 11.
665  // On x64 this is 1 + 4 + 1 + 1 + 8 == 15;
666  // Here we use the maximum of the two.
667  static const int kMaxSize = 15;
668
669 private:
670  inline uint32_t WriteLongPCJump(uint32_t pc_delta);
671
672  inline void WriteShortTaggedPC(uint32_t pc_delta, int tag);
673  inline void WriteShortTaggedData(intptr_t data_delta, int tag);
674
675  inline void WriteMode(RelocInfo::Mode rmode);
676  inline void WriteModeAndPC(uint32_t pc_delta, RelocInfo::Mode rmode);
677  inline void WriteIntData(int data_delta);
678  inline void WriteData(intptr_t data_delta);
679
680  byte* pos_;
681  byte* last_pc_;
682  int last_id_;
683  RelocInfo::Mode last_mode_;
684
685  DISALLOW_COPY_AND_ASSIGN(RelocInfoWriter);
686};
687
688
689// A RelocIterator iterates over relocation information.
690// Typical use:
691//
692//   for (RelocIterator it(code); !it.done(); it.next()) {
693//     // do something with it.rinfo() here
694//   }
695//
696// A mask can be specified to skip unwanted modes.
697class RelocIterator: public Malloced {
698 public:
699  // Create a new iterator positioned at
700  // the beginning of the reloc info.
701  // Relocation information with mode k is included in the
702  // iteration iff bit k of mode_mask is set.
703  explicit RelocIterator(Code* code, int mode_mask = -1);
704  explicit RelocIterator(const CodeDesc& desc, int mode_mask = -1);
705
706  // Iteration
707  bool done() const { return done_; }
708  void next();
709
710  // Return pointer valid until next next().
711  RelocInfo* rinfo() {
712    DCHECK(!done());
713    return &rinfo_;
714  }
715
716 private:
717  // Advance* moves the position before/after reading.
718  // *Read* reads from current byte(s) into rinfo_.
719  // *Get* just reads and returns info on current byte.
720  void Advance(int bytes = 1) { pos_ -= bytes; }
721  int AdvanceGetTag();
722  RelocInfo::Mode GetMode();
723
724  void AdvanceReadLongPCJump();
725
726  int GetShortDataTypeTag();
727  void ReadShortTaggedPC();
728  void ReadShortTaggedId();
729  void ReadShortTaggedData();
730
731  void AdvanceReadPC();
732  void AdvanceReadId();
733  void AdvanceReadInt();
734  void AdvanceReadData();
735
736  // If the given mode is wanted, set it in rinfo_ and return true.
737  // Else return false. Used for efficiently skipping unwanted modes.
738  bool SetMode(RelocInfo::Mode mode) {
739    return (mode_mask_ & (1 << mode)) ? (rinfo_.rmode_ = mode, true) : false;
740  }
741
742  byte* pos_;
743  byte* end_;
744  byte* code_age_sequence_;
745  RelocInfo rinfo_;
746  bool done_;
747  int mode_mask_;
748  int last_id_;
749  DISALLOW_COPY_AND_ASSIGN(RelocIterator);
750};
751
752
753//------------------------------------------------------------------------------
754// External function
755
756//----------------------------------------------------------------------------
757class SCTableReference;
758class Debug_Address;
759
760
761// An ExternalReference represents a C++ address used in the generated
762// code. All references to C++ functions and variables must be encapsulated in
763// an ExternalReference instance. This is done in order to track the origin of
764// all external references in the code so that they can be bound to the correct
765// addresses when deserializing a heap.
766class ExternalReference BASE_EMBEDDED {
767 public:
768  // Used in the simulator to support different native api calls.
769  enum Type {
770    // Builtin call.
771    // Object* f(v8::internal::Arguments).
772    BUILTIN_CALL,  // default
773
774    // Builtin call returning object pair.
775    // ObjectPair f(v8::internal::Arguments).
776    BUILTIN_CALL_PAIR,
777
778    // Builtin call that returns .
779    // ObjectTriple f(v8::internal::Arguments).
780    BUILTIN_CALL_TRIPLE,
781
782    // Builtin that takes float arguments and returns an int.
783    // int f(double, double).
784    BUILTIN_COMPARE_CALL,
785
786    // Builtin call that returns floating point.
787    // double f(double, double).
788    BUILTIN_FP_FP_CALL,
789
790    // Builtin call that returns floating point.
791    // double f(double).
792    BUILTIN_FP_CALL,
793
794    // Builtin call that returns floating point.
795    // double f(double, int).
796    BUILTIN_FP_INT_CALL,
797
798    // Direct call to API function callback.
799    // void f(v8::FunctionCallbackInfo&)
800    DIRECT_API_CALL,
801
802    // Call to function callback via InvokeFunctionCallback.
803    // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback)
804    PROFILING_API_CALL,
805
806    // Direct call to accessor getter callback.
807    // void f(Local<Name> property, PropertyCallbackInfo& info)
808    DIRECT_GETTER_CALL,
809
810    // Call to accessor getter callback via InvokeAccessorGetterCallback.
811    // void f(Local<Name> property, PropertyCallbackInfo& info,
812    //     AccessorNameGetterCallback callback)
813    PROFILING_GETTER_CALL
814  };
815
816  static void SetUp();
817
818  typedef void* ExternalReferenceRedirector(Isolate* isolate, void* original,
819                                            Type type);
820
821  ExternalReference() : address_(NULL) {}
822
823  ExternalReference(Address address, Isolate* isolate);
824
825  ExternalReference(ApiFunction* ptr, Type type, Isolate* isolate);
826
827  ExternalReference(Builtins::Name name, Isolate* isolate);
828
829  ExternalReference(Runtime::FunctionId id, Isolate* isolate);
830
831  ExternalReference(const Runtime::Function* f, Isolate* isolate);
832
833  explicit ExternalReference(StatsCounter* counter);
834
835  ExternalReference(Isolate::AddressId id, Isolate* isolate);
836
837  explicit ExternalReference(const SCTableReference& table_ref);
838
839  // Isolate as an external reference.
840  static ExternalReference isolate_address(Isolate* isolate);
841
842  // One-of-a-kind references. These references are not part of a general
843  // pattern. This means that they have to be added to the
844  // ExternalReferenceTable in serialize.cc manually.
845
846  static ExternalReference interpreter_dispatch_table_address(Isolate* isolate);
847  static ExternalReference interpreter_dispatch_counters(Isolate* isolate);
848
849  static ExternalReference incremental_marking_record_write_function(
850      Isolate* isolate);
851  static ExternalReference incremental_marking_record_write_code_entry_function(
852      Isolate* isolate);
853  static ExternalReference store_buffer_overflow_function(
854      Isolate* isolate);
855  static ExternalReference delete_handle_scope_extensions(Isolate* isolate);
856
857  static ExternalReference get_date_field_function(Isolate* isolate);
858  static ExternalReference date_cache_stamp(Isolate* isolate);
859
860  static ExternalReference get_make_code_young_function(Isolate* isolate);
861  static ExternalReference get_mark_code_as_executed_function(Isolate* isolate);
862
863  // Deoptimization support.
864  static ExternalReference new_deoptimizer_function(Isolate* isolate);
865  static ExternalReference compute_output_frames_function(Isolate* isolate);
866
867  static ExternalReference wasm_f32_trunc(Isolate* isolate);
868  static ExternalReference wasm_f32_floor(Isolate* isolate);
869  static ExternalReference wasm_f32_ceil(Isolate* isolate);
870  static ExternalReference wasm_f32_nearest_int(Isolate* isolate);
871  static ExternalReference wasm_f64_trunc(Isolate* isolate);
872  static ExternalReference wasm_f64_floor(Isolate* isolate);
873  static ExternalReference wasm_f64_ceil(Isolate* isolate);
874  static ExternalReference wasm_f64_nearest_int(Isolate* isolate);
875  static ExternalReference wasm_int64_to_float32(Isolate* isolate);
876  static ExternalReference wasm_uint64_to_float32(Isolate* isolate);
877  static ExternalReference wasm_int64_to_float64(Isolate* isolate);
878  static ExternalReference wasm_uint64_to_float64(Isolate* isolate);
879  static ExternalReference wasm_float32_to_int64(Isolate* isolate);
880  static ExternalReference wasm_float32_to_uint64(Isolate* isolate);
881  static ExternalReference wasm_float64_to_int64(Isolate* isolate);
882  static ExternalReference wasm_float64_to_uint64(Isolate* isolate);
883  static ExternalReference wasm_int64_div(Isolate* isolate);
884  static ExternalReference wasm_int64_mod(Isolate* isolate);
885  static ExternalReference wasm_uint64_div(Isolate* isolate);
886  static ExternalReference wasm_uint64_mod(Isolate* isolate);
887  static ExternalReference wasm_word32_ctz(Isolate* isolate);
888  static ExternalReference wasm_word64_ctz(Isolate* isolate);
889  static ExternalReference wasm_word32_popcnt(Isolate* isolate);
890  static ExternalReference wasm_word64_popcnt(Isolate* isolate);
891  static ExternalReference wasm_float64_pow(Isolate* isolate);
892
893  static ExternalReference f64_acos_wrapper_function(Isolate* isolate);
894  static ExternalReference f64_asin_wrapper_function(Isolate* isolate);
895  static ExternalReference f64_mod_wrapper_function(Isolate* isolate);
896
897  // Trap callback function for cctest/wasm/wasm-run-utils.h
898  static ExternalReference wasm_call_trap_callback_for_testing(
899      Isolate* isolate);
900
901  // Log support.
902  static ExternalReference log_enter_external_function(Isolate* isolate);
903  static ExternalReference log_leave_external_function(Isolate* isolate);
904
905  // Static variable Heap::roots_array_start()
906  static ExternalReference roots_array_start(Isolate* isolate);
907
908  // Static variable Heap::allocation_sites_list_address()
909  static ExternalReference allocation_sites_list_address(Isolate* isolate);
910
911  // Static variable StackGuard::address_of_jslimit()
912  V8_EXPORT_PRIVATE static ExternalReference address_of_stack_limit(
913      Isolate* isolate);
914
915  // Static variable StackGuard::address_of_real_jslimit()
916  static ExternalReference address_of_real_stack_limit(Isolate* isolate);
917
918  // Static variable RegExpStack::limit_address()
919  static ExternalReference address_of_regexp_stack_limit(Isolate* isolate);
920
921  // Static variables for RegExp.
922  static ExternalReference address_of_static_offsets_vector(Isolate* isolate);
923  static ExternalReference address_of_regexp_stack_memory_address(
924      Isolate* isolate);
925  static ExternalReference address_of_regexp_stack_memory_size(
926      Isolate* isolate);
927
928  // Write barrier.
929  static ExternalReference store_buffer_top(Isolate* isolate);
930
931  // Used for fast allocation in generated code.
932  static ExternalReference new_space_allocation_top_address(Isolate* isolate);
933  static ExternalReference new_space_allocation_limit_address(Isolate* isolate);
934  static ExternalReference old_space_allocation_top_address(Isolate* isolate);
935  static ExternalReference old_space_allocation_limit_address(Isolate* isolate);
936
937  static ExternalReference mod_two_doubles_operation(Isolate* isolate);
938  static ExternalReference power_double_double_function(Isolate* isolate);
939
940  static ExternalReference handle_scope_next_address(Isolate* isolate);
941  static ExternalReference handle_scope_limit_address(Isolate* isolate);
942  static ExternalReference handle_scope_level_address(Isolate* isolate);
943
944  static ExternalReference scheduled_exception_address(Isolate* isolate);
945  static ExternalReference address_of_pending_message_obj(Isolate* isolate);
946
947  // Static variables containing common double constants.
948  static ExternalReference address_of_min_int();
949  static ExternalReference address_of_one_half();
950  static ExternalReference address_of_minus_one_half();
951  static ExternalReference address_of_negative_infinity();
952  static ExternalReference address_of_the_hole_nan();
953  static ExternalReference address_of_uint32_bias();
954
955  // Static variables containing simd constants.
956  static ExternalReference address_of_float_abs_constant();
957  static ExternalReference address_of_float_neg_constant();
958  static ExternalReference address_of_double_abs_constant();
959  static ExternalReference address_of_double_neg_constant();
960
961  // IEEE 754 functions.
962  static ExternalReference ieee754_acos_function(Isolate* isolate);
963  static ExternalReference ieee754_acosh_function(Isolate* isolate);
964  static ExternalReference ieee754_asin_function(Isolate* isolate);
965  static ExternalReference ieee754_asinh_function(Isolate* isolate);
966  static ExternalReference ieee754_atan_function(Isolate* isolate);
967  static ExternalReference ieee754_atanh_function(Isolate* isolate);
968  static ExternalReference ieee754_atan2_function(Isolate* isolate);
969  static ExternalReference ieee754_cbrt_function(Isolate* isolate);
970  static ExternalReference ieee754_cos_function(Isolate* isolate);
971  static ExternalReference ieee754_cosh_function(Isolate* isolate);
972  static ExternalReference ieee754_exp_function(Isolate* isolate);
973  static ExternalReference ieee754_expm1_function(Isolate* isolate);
974  static ExternalReference ieee754_log_function(Isolate* isolate);
975  static ExternalReference ieee754_log1p_function(Isolate* isolate);
976  static ExternalReference ieee754_log10_function(Isolate* isolate);
977  static ExternalReference ieee754_log2_function(Isolate* isolate);
978  static ExternalReference ieee754_sin_function(Isolate* isolate);
979  static ExternalReference ieee754_sinh_function(Isolate* isolate);
980  static ExternalReference ieee754_tan_function(Isolate* isolate);
981  static ExternalReference ieee754_tanh_function(Isolate* isolate);
982
983  static ExternalReference libc_memchr_function(Isolate* isolate);
984
985  static ExternalReference page_flags(Page* page);
986
987  static ExternalReference ForDeoptEntry(Address entry);
988
989  static ExternalReference cpu_features();
990
991  static ExternalReference is_tail_call_elimination_enabled_address(
992      Isolate* isolate);
993
994  static ExternalReference debug_is_active_address(Isolate* isolate);
995  static ExternalReference debug_hook_on_function_call_address(
996      Isolate* isolate);
997  static ExternalReference debug_after_break_target_address(Isolate* isolate);
998
999  static ExternalReference is_profiling_address(Isolate* isolate);
1000  static ExternalReference invoke_function_callback(Isolate* isolate);
1001  static ExternalReference invoke_accessor_getter_callback(Isolate* isolate);
1002
1003  static ExternalReference promise_hook_or_debug_is_active_address(
1004      Isolate* isolate);
1005
1006  V8_EXPORT_PRIVATE static ExternalReference runtime_function_table_address(
1007      Isolate* isolate);
1008
1009  Address address() const { return reinterpret_cast<Address>(address_); }
1010
1011  // Used to read out the last step action of the debugger.
1012  static ExternalReference debug_last_step_action_address(Isolate* isolate);
1013
1014  // Used to check for suspended generator, used for stepping across await call.
1015  static ExternalReference debug_suspended_generator_address(Isolate* isolate);
1016
1017  // Used to store the frame pointer to drop to when restarting a frame.
1018  static ExternalReference debug_restart_fp_address(Isolate* isolate);
1019
1020#ifndef V8_INTERPRETED_REGEXP
1021  // C functions called from RegExp generated code.
1022
1023  // Function NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()
1024  static ExternalReference re_case_insensitive_compare_uc16(Isolate* isolate);
1025
1026  // Function RegExpMacroAssembler*::CheckStackGuardState()
1027  static ExternalReference re_check_stack_guard_state(Isolate* isolate);
1028
1029  // Function NativeRegExpMacroAssembler::GrowStack()
1030  static ExternalReference re_grow_stack(Isolate* isolate);
1031
1032  // byte NativeRegExpMacroAssembler::word_character_bitmap
1033  static ExternalReference re_word_character_map();
1034
1035#endif
1036
1037  // This lets you register a function that rewrites all external references.
1038  // Used by the ARM simulator to catch calls to external references.
1039  static void set_redirector(Isolate* isolate,
1040                             ExternalReferenceRedirector* redirector) {
1041    // We can't stack them.
1042    DCHECK(isolate->external_reference_redirector() == NULL);
1043    isolate->set_external_reference_redirector(
1044        reinterpret_cast<ExternalReferenceRedirectorPointer*>(redirector));
1045  }
1046
1047  static ExternalReference stress_deopt_count(Isolate* isolate);
1048
1049  static ExternalReference fixed_typed_array_base_data_offset();
1050
1051 private:
1052  explicit ExternalReference(void* address)
1053      : address_(address) {}
1054
1055  static void* Redirect(Isolate* isolate,
1056                        Address address_arg,
1057                        Type type = ExternalReference::BUILTIN_CALL) {
1058    ExternalReferenceRedirector* redirector =
1059        reinterpret_cast<ExternalReferenceRedirector*>(
1060            isolate->external_reference_redirector());
1061    void* address = reinterpret_cast<void*>(address_arg);
1062    void* answer =
1063        (redirector == NULL) ? address : (*redirector)(isolate, address, type);
1064    return answer;
1065  }
1066
1067  void* address_;
1068};
1069
1070V8_EXPORT_PRIVATE bool operator==(ExternalReference, ExternalReference);
1071bool operator!=(ExternalReference, ExternalReference);
1072
1073size_t hash_value(ExternalReference);
1074
1075V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, ExternalReference);
1076
1077// -----------------------------------------------------------------------------
1078// Utility functions
1079void* libc_memchr(void* string, int character, size_t search_length);
1080
1081inline int NumberOfBitsSet(uint32_t x) {
1082  unsigned int num_bits_set;
1083  for (num_bits_set = 0; x; x >>= 1) {
1084    num_bits_set += x & 1;
1085  }
1086  return num_bits_set;
1087}
1088
1089// Computes pow(x, y) with the special cases in the spec for Math.pow.
1090double power_helper(Isolate* isolate, double x, double y);
1091double power_double_int(double x, int y);
1092double power_double_double(double x, double y);
1093
1094// Helper class for generating code or data associated with the code
1095// right after a call instruction. As an example this can be used to
1096// generate safepoint data after calls for crankshaft.
1097class CallWrapper {
1098 public:
1099  CallWrapper() { }
1100  virtual ~CallWrapper() { }
1101  // Called just before emitting a call. Argument is the size of the generated
1102  // call code.
1103  virtual void BeforeCall(int call_size) const = 0;
1104  // Called just after emitting a call, i.e., at the return site for the call.
1105  virtual void AfterCall() const = 0;
1106  // Return whether call needs to check for debug stepping.
1107  virtual bool NeedsDebugHookCheck() const { return false; }
1108};
1109
1110
1111class NullCallWrapper : public CallWrapper {
1112 public:
1113  NullCallWrapper() { }
1114  virtual ~NullCallWrapper() { }
1115  virtual void BeforeCall(int call_size) const { }
1116  virtual void AfterCall() const { }
1117};
1118
1119
1120class CheckDebugStepCallWrapper : public CallWrapper {
1121 public:
1122  CheckDebugStepCallWrapper() {}
1123  virtual ~CheckDebugStepCallWrapper() {}
1124  virtual void BeforeCall(int call_size) const {}
1125  virtual void AfterCall() const {}
1126  virtual bool NeedsDebugHookCheck() const { return true; }
1127};
1128
1129
1130// -----------------------------------------------------------------------------
1131// Constant pool support
1132
1133class ConstantPoolEntry {
1134 public:
1135  ConstantPoolEntry() {}
1136  ConstantPoolEntry(int position, intptr_t value, bool sharing_ok)
1137      : position_(position),
1138        merged_index_(sharing_ok ? SHARING_ALLOWED : SHARING_PROHIBITED),
1139        value_(value) {}
1140  ConstantPoolEntry(int position, double value)
1141      : position_(position), merged_index_(SHARING_ALLOWED), value64_(value) {}
1142
1143  int position() const { return position_; }
1144  bool sharing_ok() const { return merged_index_ != SHARING_PROHIBITED; }
1145  bool is_merged() const { return merged_index_ >= 0; }
1146  int merged_index(void) const {
1147    DCHECK(is_merged());
1148    return merged_index_;
1149  }
1150  void set_merged_index(int index) {
1151    merged_index_ = index;
1152    DCHECK(is_merged());
1153  }
1154  int offset(void) const {
1155    DCHECK(merged_index_ >= 0);
1156    return merged_index_;
1157  }
1158  void set_offset(int offset) {
1159    DCHECK(offset >= 0);
1160    merged_index_ = offset;
1161  }
1162  intptr_t value() const { return value_; }
1163  uint64_t value64() const { return bit_cast<uint64_t>(value64_); }
1164
1165  enum Type { INTPTR, DOUBLE, NUMBER_OF_TYPES };
1166
1167  static int size(Type type) {
1168    return (type == INTPTR) ? kPointerSize : kDoubleSize;
1169  }
1170
1171  enum Access { REGULAR, OVERFLOWED };
1172
1173 private:
1174  int position_;
1175  int merged_index_;
1176  union {
1177    intptr_t value_;
1178    double value64_;
1179  };
1180  enum { SHARING_PROHIBITED = -2, SHARING_ALLOWED = -1 };
1181};
1182
1183
1184// -----------------------------------------------------------------------------
1185// Embedded constant pool support
1186
1187class ConstantPoolBuilder BASE_EMBEDDED {
1188 public:
1189  ConstantPoolBuilder(int ptr_reach_bits, int double_reach_bits);
1190
1191  // Add pointer-sized constant to the embedded constant pool
1192  ConstantPoolEntry::Access AddEntry(int position, intptr_t value,
1193                                     bool sharing_ok) {
1194    ConstantPoolEntry entry(position, value, sharing_ok);
1195    return AddEntry(entry, ConstantPoolEntry::INTPTR);
1196  }
1197
1198  // Add double constant to the embedded constant pool
1199  ConstantPoolEntry::Access AddEntry(int position, double value) {
1200    ConstantPoolEntry entry(position, value);
1201    return AddEntry(entry, ConstantPoolEntry::DOUBLE);
1202  }
1203
1204  // Previews the access type required for the next new entry to be added.
1205  ConstantPoolEntry::Access NextAccess(ConstantPoolEntry::Type type) const;
1206
1207  bool IsEmpty() {
1208    return info_[ConstantPoolEntry::INTPTR].entries.empty() &&
1209           info_[ConstantPoolEntry::INTPTR].shared_entries.empty() &&
1210           info_[ConstantPoolEntry::DOUBLE].entries.empty() &&
1211           info_[ConstantPoolEntry::DOUBLE].shared_entries.empty();
1212  }
1213
1214  // Emit the constant pool.  Invoke only after all entries have been
1215  // added and all instructions have been emitted.
1216  // Returns position of the emitted pool (zero implies no constant pool).
1217  int Emit(Assembler* assm);
1218
1219  // Returns the label associated with the start of the constant pool.
1220  // Linking to this label in the function prologue may provide an
1221  // efficient means of constant pool pointer register initialization
1222  // on some architectures.
1223  inline Label* EmittedPosition() { return &emitted_label_; }
1224
1225 private:
1226  ConstantPoolEntry::Access AddEntry(ConstantPoolEntry& entry,
1227                                     ConstantPoolEntry::Type type);
1228  void EmitSharedEntries(Assembler* assm, ConstantPoolEntry::Type type);
1229  void EmitGroup(Assembler* assm, ConstantPoolEntry::Access access,
1230                 ConstantPoolEntry::Type type);
1231
1232  struct PerTypeEntryInfo {
1233    PerTypeEntryInfo() : regular_count(0), overflow_start(-1) {}
1234    bool overflow() const {
1235      return (overflow_start >= 0 &&
1236              overflow_start < static_cast<int>(entries.size()));
1237    }
1238    int regular_reach_bits;
1239    int regular_count;
1240    int overflow_start;
1241    std::vector<ConstantPoolEntry> entries;
1242    std::vector<ConstantPoolEntry> shared_entries;
1243  };
1244
1245  Label emitted_label_;  // Records pc_offset of emitted pool
1246  PerTypeEntryInfo info_[ConstantPoolEntry::NUMBER_OF_TYPES];
1247};
1248
1249}  // namespace internal
1250}  // namespace v8
1251#endif  // V8_ASSEMBLER_H_
1252