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