• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
48 namespace v8 {
49 
50 // Forward declarations.
51 class ApiFunction;
52 
53 namespace internal {
54 
55 // Forward declarations.
56 class SourcePosition;
57 class StatsCounter;
58 
59 // -----------------------------------------------------------------------------
60 // Platform independent assembler base class.
61 
62 enum class CodeObjectRequired { kNo, kYes };
63 
64 
65 class AssemblerBase: public Malloced {
66  public:
67   AssemblerBase(Isolate* isolate, void* buffer, int buffer_size);
68   virtual ~AssemblerBase();
69 
isolate()70   Isolate* isolate() const { return isolate_; }
jit_cookie()71   int jit_cookie() const { return jit_cookie_; }
72 
emit_debug_code()73   bool emit_debug_code() const { return emit_debug_code_; }
set_emit_debug_code(bool value)74   void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
75 
serializer_enabled()76   bool serializer_enabled() const { return serializer_enabled_; }
enable_serializer()77   void enable_serializer() { serializer_enabled_ = true; }
78 
predictable_code_size()79   bool predictable_code_size() const { return predictable_code_size_; }
set_predictable_code_size(bool value)80   void set_predictable_code_size(bool value) { predictable_code_size_ = value; }
81 
enabled_cpu_features()82   uint64_t enabled_cpu_features() const { return enabled_cpu_features_; }
set_enabled_cpu_features(uint64_t 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.
IsEnabled(CpuFeature f)88   bool IsEnabled(CpuFeature f) {
89     return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0;
90   }
EnableCpuFeature(CpuFeature f)91   void EnableCpuFeature(CpuFeature f) {
92     enabled_cpu_features_ |= (static_cast<uint64_t>(1) << f);
93   }
94 
is_constant_pool_available()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.
QuietNaN(HeapObject * nan)107   static void QuietNaN(HeapObject* nan) { }
108 
pc_offset()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.
AbortedCodeGeneration()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 
set_constant_pool_available(bool available)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.
160 class DontEmitDebugCodeScope BASE_EMBEDDED {
161  public:
DontEmitDebugCodeScope(AssemblerBase * assembler)162   explicit DontEmitDebugCodeScope(AssemblerBase* assembler)
163       : assembler_(assembler), old_value_(assembler->emit_debug_code()) {
164     assembler_->set_emit_debug_code(false);
165   }
~DontEmitDebugCodeScope()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.
177 class PredictableCodeSizeScope {
178  public:
179   explicit PredictableCodeSizeScope(AssemblerBase* assembler);
180   PredictableCodeSizeScope(AssemblerBase* assembler, int expected_size);
181   ~PredictableCodeSizeScope();
ExpectSize(int expected_size)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.
193 class 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 //   }
224 class CpuFeatures : public AllStatic {
225  public:
Probe(bool cross_compile)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 
SupportedFeatures()233   static unsigned SupportedFeatures() {
234     Probe(false);
235     return supported_;
236   }
237 
IsSupported(CpuFeature f)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 
icache_line_size()246   static inline unsigned icache_line_size() {
247     DCHECK(icache_line_size_ != 0);
248     return icache_line_size_;
249   }
250 
dcache_line_size()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 
276 enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs };
277 
278 enum 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).
285 enum 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 
298 class 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 
RelocInfo(Isolate * isolate)375   explicit RelocInfo(Isolate* isolate) : isolate_(isolate) {
376     DCHECK_NOT_NULL(isolate);
377   }
378 
RelocInfo(Isolate * isolate,byte * pc,Mode rmode,intptr_t data,Code * host)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 
IsRealRelocMode(Mode mode)384   static inline bool IsRealRelocMode(Mode mode) {
385     return mode >= FIRST_REAL_RELOC_MODE && mode <= LAST_REAL_RELOC_MODE;
386   }
IsCodeTarget(Mode mode)387   static inline bool IsCodeTarget(Mode mode) {
388     return mode <= LAST_CODE_ENUM;
389   }
IsEmbeddedObject(Mode mode)390   static inline bool IsEmbeddedObject(Mode mode) {
391     return mode == EMBEDDED_OBJECT;
392   }
IsCell(Mode mode)393   static inline bool IsCell(Mode mode) { return mode == CELL; }
IsRuntimeEntry(Mode mode)394   static inline bool IsRuntimeEntry(Mode mode) {
395     return mode == RUNTIME_ENTRY;
396   }
397   // Is the relocation mode affected by GC?
IsGCRelocMode(Mode mode)398   static inline bool IsGCRelocMode(Mode mode) {
399     return mode <= LAST_GCED_ENUM;
400   }
IsComment(Mode mode)401   static inline bool IsComment(Mode mode) {
402     return mode == COMMENT;
403   }
IsConstPool(Mode mode)404   static inline bool IsConstPool(Mode mode) {
405     return mode == CONST_POOL;
406   }
IsVeneerPool(Mode mode)407   static inline bool IsVeneerPool(Mode mode) {
408     return mode == VENEER_POOL;
409   }
IsDeoptPosition(Mode mode)410   static inline bool IsDeoptPosition(Mode mode) {
411     return mode == DEOPT_SCRIPT_OFFSET || mode == DEOPT_INLINING_ID;
412   }
IsDeoptReason(Mode mode)413   static inline bool IsDeoptReason(Mode mode) {
414     return mode == DEOPT_REASON;
415   }
IsDeoptId(Mode mode)416   static inline bool IsDeoptId(Mode mode) {
417     return mode == DEOPT_ID;
418   }
IsExternalReference(Mode mode)419   static inline bool IsExternalReference(Mode mode) {
420     return mode == EXTERNAL_REFERENCE;
421   }
IsInternalReference(Mode mode)422   static inline bool IsInternalReference(Mode mode) {
423     return mode == INTERNAL_REFERENCE;
424   }
IsInternalReferenceEncoded(Mode mode)425   static inline bool IsInternalReferenceEncoded(Mode mode) {
426     return mode == INTERNAL_REFERENCE_ENCODED;
427   }
IsDebugBreakSlot(Mode mode)428   static inline bool IsDebugBreakSlot(Mode mode) {
429     return IsDebugBreakSlotAtPosition(mode) || IsDebugBreakSlotAtReturn(mode) ||
430            IsDebugBreakSlotAtCall(mode) || IsDebugBreakSlotAtTailCall(mode);
431   }
IsDebugBreakSlotAtPosition(Mode mode)432   static inline bool IsDebugBreakSlotAtPosition(Mode mode) {
433     return mode == DEBUG_BREAK_SLOT_AT_POSITION;
434   }
IsDebugBreakSlotAtReturn(Mode mode)435   static inline bool IsDebugBreakSlotAtReturn(Mode mode) {
436     return mode == DEBUG_BREAK_SLOT_AT_RETURN;
437   }
IsDebugBreakSlotAtCall(Mode mode)438   static inline bool IsDebugBreakSlotAtCall(Mode mode) {
439     return mode == DEBUG_BREAK_SLOT_AT_CALL;
440   }
IsDebugBreakSlotAtTailCall(Mode mode)441   static inline bool IsDebugBreakSlotAtTailCall(Mode mode) {
442     return mode == DEBUG_BREAK_SLOT_AT_TAIL_CALL;
443   }
IsNone(Mode mode)444   static inline bool IsNone(Mode mode) {
445     return mode == NONE32 || mode == NONE64;
446   }
IsCodeAgeSequence(Mode mode)447   static inline bool IsCodeAgeSequence(Mode mode) {
448     return mode == CODE_AGE_SEQUENCE;
449   }
IsWasmMemoryReference(Mode mode)450   static inline bool IsWasmMemoryReference(Mode mode) {
451     return mode == WASM_MEMORY_REFERENCE;
452   }
IsWasmMemorySizeReference(Mode mode)453   static inline bool IsWasmMemorySizeReference(Mode mode) {
454     return mode == WASM_MEMORY_SIZE_REFERENCE;
455   }
IsWasmGlobalReference(Mode mode)456   static inline bool IsWasmGlobalReference(Mode mode) {
457     return mode == WASM_GLOBAL_REFERENCE;
458   }
IsWasmFunctionTableSizeReference(Mode mode)459   static inline bool IsWasmFunctionTableSizeReference(Mode mode) {
460     return mode == WASM_FUNCTION_TABLE_SIZE_REFERENCE;
461   }
IsWasmReference(Mode mode)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   }
IsWasmSizeReference(Mode mode)467   static inline bool IsWasmSizeReference(Mode mode) {
468     return mode == WASM_MEMORY_SIZE_REFERENCE ||
469            mode == WASM_FUNCTION_TABLE_SIZE_REFERENCE;
470   }
IsWasmPtrReference(Mode mode)471   static inline bool IsWasmPtrReference(Mode mode) {
472     return mode == WASM_MEMORY_REFERENCE || mode == WASM_GLOBAL_REFERENCE;
473   }
IsWasmProtectedLanding(Mode mode)474   static inline bool IsWasmProtectedLanding(Mode mode) {
475     return mode == WASM_PROTECTED_INSTRUCTION_LANDING;
476   }
477 
ModeMask(Mode mode)478   static inline int ModeMask(Mode mode) { return 1 << mode; }
479 
480   // Accessors
isolate()481   Isolate* isolate() const { return isolate_; }
pc()482   byte* pc() const { return pc_; }
set_pc(byte * pc)483   void set_pc(byte* pc) { pc_ = pc; }
rmode()484   Mode rmode() const {  return rmode_; }
data()485   intptr_t data() const { return data_; }
host()486   Code* host() const { return host_; }
set_host(Code * 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.
645 class RelocInfoWriter BASE_EMBEDDED {
646  public:
RelocInfoWriter()647   RelocInfoWriter() : pos_(NULL), last_pc_(NULL), last_id_(0) {}
RelocInfoWriter(byte * pos,byte * pc)648   RelocInfoWriter(byte* pos, byte* pc) : pos_(pos), last_pc_(pc), last_id_(0) {}
649 
pos()650   byte* pos() const { return pos_; }
last_pc()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.
Reposition(byte * pos,byte * pc)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.
697 class 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
done()707   bool done() const { return done_; }
708   void next();
709 
710   // Return pointer valid until next next().
rinfo()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.
SetMode(RelocInfo::Mode mode)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 //----------------------------------------------------------------------------
757 class SCTableReference;
758 class 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.
766 class 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 
ExternalReference()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 
address()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.
set_redirector(Isolate * isolate,ExternalReferenceRedirector * redirector)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:
ExternalReference(void * address)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 
1070 V8_EXPORT_PRIVATE bool operator==(ExternalReference, ExternalReference);
1071 bool operator!=(ExternalReference, ExternalReference);
1072 
1073 size_t hash_value(ExternalReference);
1074 
1075 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, ExternalReference);
1076 
1077 // -----------------------------------------------------------------------------
1078 // Utility functions
1079 void* libc_memchr(void* string, int character, size_t search_length);
1080 
NumberOfBitsSet(uint32_t x)1081 inline 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.
1090 double power_helper(Isolate* isolate, double x, double y);
1091 double power_double_int(double x, int y);
1092 double 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.
1097 class CallWrapper {
1098  public:
CallWrapper()1099   CallWrapper() { }
~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.
NeedsDebugHookCheck()1107   virtual bool NeedsDebugHookCheck() const { return false; }
1108 };
1109 
1110 
1111 class NullCallWrapper : public CallWrapper {
1112  public:
NullCallWrapper()1113   NullCallWrapper() { }
~NullCallWrapper()1114   virtual ~NullCallWrapper() { }
BeforeCall(int call_size)1115   virtual void BeforeCall(int call_size) const { }
AfterCall()1116   virtual void AfterCall() const { }
1117 };
1118 
1119 
1120 class CheckDebugStepCallWrapper : public CallWrapper {
1121  public:
CheckDebugStepCallWrapper()1122   CheckDebugStepCallWrapper() {}
~CheckDebugStepCallWrapper()1123   virtual ~CheckDebugStepCallWrapper() {}
BeforeCall(int call_size)1124   virtual void BeforeCall(int call_size) const {}
AfterCall()1125   virtual void AfterCall() const {}
NeedsDebugHookCheck()1126   virtual bool NeedsDebugHookCheck() const { return true; }
1127 };
1128 
1129 
1130 // -----------------------------------------------------------------------------
1131 // Constant pool support
1132 
1133 class ConstantPoolEntry {
1134  public:
ConstantPoolEntry()1135   ConstantPoolEntry() {}
ConstantPoolEntry(int position,intptr_t value,bool sharing_ok)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) {}
ConstantPoolEntry(int position,double value)1140   ConstantPoolEntry(int position, double value)
1141       : position_(position), merged_index_(SHARING_ALLOWED), value64_(value) {}
1142 
position()1143   int position() const { return position_; }
sharing_ok()1144   bool sharing_ok() const { return merged_index_ != SHARING_PROHIBITED; }
is_merged()1145   bool is_merged() const { return merged_index_ >= 0; }
merged_index(void)1146   int merged_index(void) const {
1147     DCHECK(is_merged());
1148     return merged_index_;
1149   }
set_merged_index(int index)1150   void set_merged_index(int index) {
1151     merged_index_ = index;
1152     DCHECK(is_merged());
1153   }
offset(void)1154   int offset(void) const {
1155     DCHECK(merged_index_ >= 0);
1156     return merged_index_;
1157   }
set_offset(int offset)1158   void set_offset(int offset) {
1159     DCHECK(offset >= 0);
1160     merged_index_ = offset;
1161   }
value()1162   intptr_t value() const { return value_; }
value64()1163   uint64_t value64() const { return bit_cast<uint64_t>(value64_); }
1164 
1165   enum Type { INTPTR, DOUBLE, NUMBER_OF_TYPES };
1166 
size(Type type)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 
1187 class 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
AddEntry(int position,intptr_t value,bool sharing_ok)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
AddEntry(int position,double value)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 
IsEmpty()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.
EmittedPosition()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 {
PerTypeEntryInfoPerTypeEntryInfo1233     PerTypeEntryInfo() : regular_count(0), overflow_start(-1) {}
overflowPerTypeEntryInfo1234     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