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