The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / assembler.h @ f230a1cf

History | View | Annotate | Download (37.4 KB)

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 "v8.h"
39

    
40
#include "allocation.h"
41
#include "builtins.h"
42
#include "gdb-jit.h"
43
#include "isolate.h"
44
#include "runtime.h"
45
#include "token.h"
46

    
47
namespace v8 {
48

    
49
class ApiFunction;
50

    
51
namespace internal {
52

    
53
class StatsCounter;
54
// -----------------------------------------------------------------------------
55
// Platform independent assembler base class.
56

    
57
class AssemblerBase: public Malloced {
58
 public:
59
  AssemblerBase(Isolate* isolate, void* buffer, int buffer_size);
60
  virtual ~AssemblerBase();
61

    
62
  Isolate* isolate() const { return isolate_; }
63
  int jit_cookie() const { return jit_cookie_; }
64

    
65
  bool emit_debug_code() const { return emit_debug_code_; }
66
  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
67

    
68
  bool predictable_code_size() const { return predictable_code_size_; }
69
  void set_predictable_code_size(bool value) { predictable_code_size_ = value; }
70

    
71
  uint64_t enabled_cpu_features() const { return enabled_cpu_features_; }
72
  void set_enabled_cpu_features(uint64_t features) {
73
    enabled_cpu_features_ = features;
74
  }
75
  bool IsEnabled(CpuFeature f) {
76
    return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0;
77
  }
78

    
79
  // Overwrite a host NaN with a quiet target NaN.  Used by mksnapshot for
80
  // cross-snapshotting.
81
  static void QuietNaN(HeapObject* nan) { }
82

    
83
  int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
84

    
85
  static const int kMinimalBufferSize = 4*KB;
86

    
87
 protected:
88
  // The buffer into which code and relocation info are generated. It could
89
  // either be owned by the assembler or be provided externally.
90
  byte* buffer_;
91
  int buffer_size_;
92
  bool own_buffer_;
93

    
94
  // The program counter, which points into the buffer above and moves forward.
95
  byte* pc_;
96

    
97
 private:
98
  Isolate* isolate_;
99
  int jit_cookie_;
100
  uint64_t enabled_cpu_features_;
101
  bool emit_debug_code_;
102
  bool predictable_code_size_;
103
};
104

    
105

    
106
// Avoids using instructions that vary in size in unpredictable ways between the
107
// snapshot and the running VM.
108
class PredictableCodeSizeScope {
109
 public:
110
  PredictableCodeSizeScope(AssemblerBase* assembler, int expected_size);
111
  ~PredictableCodeSizeScope();
112

    
113
 private:
114
  AssemblerBase* assembler_;
115
  int expected_size_;
116
  int start_offset_;
117
  bool old_value_;
118
};
119

    
120

    
121
// Enable a specified feature within a scope.
122
class CpuFeatureScope BASE_EMBEDDED {
123
 public:
124
#ifdef DEBUG
125
  CpuFeatureScope(AssemblerBase* assembler, CpuFeature f);
126
  ~CpuFeatureScope();
127

    
128
 private:
129
  AssemblerBase* assembler_;
130
  uint64_t old_enabled_;
131
#else
132
  CpuFeatureScope(AssemblerBase* assembler, CpuFeature f) {}
133
#endif
134
};
135

    
136

    
137
// Enable a unsupported feature within a scope for cross-compiling for a
138
// different CPU.
139
class PlatformFeatureScope BASE_EMBEDDED {
140
 public:
141
  explicit PlatformFeatureScope(CpuFeature f);
142
  ~PlatformFeatureScope();
143

    
144
 private:
145
  uint64_t old_cross_compile_;
146
};
147

    
148

    
149
// -----------------------------------------------------------------------------
150
// Labels represent pc locations; they are typically jump or call targets.
151
// After declaration, a label can be freely used to denote known or (yet)
152
// unknown pc location. Assembler::bind() is used to bind a label to the
153
// current pc. A label can be bound only once.
154

    
155
class Label BASE_EMBEDDED {
156
 public:
157
  enum Distance {
158
    kNear, kFar
159
  };
160

    
161
  INLINE(Label()) {
162
    Unuse();
163
    UnuseNear();
164
  }
165

    
166
  INLINE(~Label()) {
167
    ASSERT(!is_linked());
168
    ASSERT(!is_near_linked());
169
  }
170

    
171
  INLINE(void Unuse()) { pos_ = 0; }
172
  INLINE(void UnuseNear()) { near_link_pos_ = 0; }
173

    
174
  INLINE(bool is_bound() const) { return pos_ <  0; }
175
  INLINE(bool is_unused() const) { return pos_ == 0 && near_link_pos_ == 0; }
176
  INLINE(bool is_linked() const) { return pos_ >  0; }
177
  INLINE(bool is_near_linked() const) { return near_link_pos_ > 0; }
178

    
179
  // Returns the position of bound or linked labels. Cannot be used
180
  // for unused labels.
181
  int pos() const;
182
  int near_link_pos() const { return near_link_pos_ - 1; }
183

    
184
 private:
185
  // pos_ encodes both the binding state (via its sign)
186
  // and the binding position (via its value) of a label.
187
  //
188
  // pos_ <  0  bound label, pos() returns the jump target position
189
  // pos_ == 0  unused label
190
  // pos_ >  0  linked label, pos() returns the last reference position
191
  int pos_;
192

    
193
  // Behaves like |pos_| in the "> 0" case, but for near jumps to this label.
194
  int near_link_pos_;
195

    
196
  void bind_to(int pos)  {
197
    pos_ = -pos - 1;
198
    ASSERT(is_bound());
199
  }
200
  void link_to(int pos, Distance distance = kFar) {
201
    if (distance == kNear) {
202
      near_link_pos_ = pos + 1;
203
      ASSERT(is_near_linked());
204
    } else {
205
      pos_ = pos + 1;
206
      ASSERT(is_linked());
207
    }
208
  }
209

    
210
  friend class Assembler;
211
  friend class Displacement;
212
  friend class RegExpMacroAssemblerIrregexp;
213
};
214

    
215

    
216
enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs };
217

    
218

    
219
// -----------------------------------------------------------------------------
220
// Relocation information
221

    
222

    
223
// Relocation information consists of the address (pc) of the datum
224
// to which the relocation information applies, the relocation mode
225
// (rmode), and an optional data field. The relocation mode may be
226
// "descriptive" and not indicate a need for relocation, but simply
227
// describe a property of the datum. Such rmodes are useful for GC
228
// and nice disassembly output.
229

    
230
class RelocInfo BASE_EMBEDDED {
231
 public:
232
  // The constant kNoPosition is used with the collecting of source positions
233
  // in the relocation information. Two types of source positions are collected
234
  // "position" (RelocMode position) and "statement position" (RelocMode
235
  // statement_position). The "position" is collected at places in the source
236
  // code which are of interest when making stack traces to pin-point the source
237
  // location of a stack frame as close as possible. The "statement position" is
238
  // collected at the beginning at each statement, and is used to indicate
239
  // possible break locations. kNoPosition is used to indicate an
240
  // invalid/uninitialized position value.
241
  static const int kNoPosition = -1;
242

    
243
  // This string is used to add padding comments to the reloc info in cases
244
  // where we are not sure to have enough space for patching in during
245
  // lazy deoptimization. This is the case if we have indirect calls for which
246
  // we do not normally record relocation info.
247
  static const char* const kFillerCommentString;
248

    
249
  // The minimum size of a comment is equal to three bytes for the extra tagged
250
  // pc + the tag for the data, and kPointerSize for the actual pointer to the
251
  // comment.
252
  static const int kMinRelocCommentSize = 3 + kPointerSize;
253

    
254
  // The maximum size for a call instruction including pc-jump.
255
  static const int kMaxCallSize = 6;
256

    
257
  // The maximum pc delta that will use the short encoding.
258
  static const int kMaxSmallPCDelta;
259

    
260
  enum Mode {
261
    // Please note the order is important (see IsCodeTarget, IsGCRelocMode).
262
    CODE_TARGET,  // Code target which is not any of the above.
263
    CODE_TARGET_WITH_ID,
264
    CONSTRUCT_CALL,  // code target that is a call to a JavaScript constructor.
265
    CODE_TARGET_CONTEXT,  // Code target used for contextual loads and stores.
266
    DEBUG_BREAK,  // Code target for the debugger statement.
267
    EMBEDDED_OBJECT,
268
    CELL,
269

    
270
    // Everything after runtime_entry (inclusive) is not GC'ed.
271
    RUNTIME_ENTRY,
272
    JS_RETURN,  // Marks start of the ExitJSFrame code.
273
    COMMENT,
274
    POSITION,  // See comment for kNoPosition above.
275
    STATEMENT_POSITION,  // See comment for kNoPosition above.
276
    DEBUG_BREAK_SLOT,  // Additional code inserted for debug break slot.
277
    EXTERNAL_REFERENCE,  // The address of an external C++ function.
278
    INTERNAL_REFERENCE,  // An address inside the same function.
279

    
280
    // Marks a constant pool. Only used on ARM.
281
    // It uses a custom noncompact encoding.
282
    CONST_POOL,
283

    
284
    // add more as needed
285
    // Pseudo-types
286
    NUMBER_OF_MODES,  // There are at most 15 modes with noncompact encoding.
287
    NONE32,  // never recorded 32-bit value
288
    NONE64,  // never recorded 64-bit value
289
    CODE_AGE_SEQUENCE,  // Not stored in RelocInfo array, used explictly by
290
                        // code aging.
291
    FIRST_REAL_RELOC_MODE = CODE_TARGET,
292
    LAST_REAL_RELOC_MODE = CONST_POOL,
293
    FIRST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE,
294
    LAST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE,
295
    LAST_CODE_ENUM = DEBUG_BREAK,
296
    LAST_GCED_ENUM = CELL,
297
    // Modes <= LAST_COMPACT_ENUM are guaranteed to have compact encoding.
298
    LAST_COMPACT_ENUM = CODE_TARGET_WITH_ID,
299
    LAST_STANDARD_NONCOMPACT_ENUM = INTERNAL_REFERENCE
300
  };
301

    
302

    
303
  RelocInfo() {}
304

    
305
  RelocInfo(byte* pc, Mode rmode, intptr_t data, Code* host)
306
      : pc_(pc), rmode_(rmode), data_(data), host_(host) {
307
  }
308
  RelocInfo(byte* pc, double data64)
309
      : pc_(pc), rmode_(NONE64), data64_(data64), host_(NULL) {
310
  }
311

    
312
  static inline bool IsRealRelocMode(Mode mode) {
313
    return mode >= FIRST_REAL_RELOC_MODE &&
314
        mode <= LAST_REAL_RELOC_MODE;
315
  }
316
  static inline bool IsPseudoRelocMode(Mode mode) {
317
    ASSERT(!IsRealRelocMode(mode));
318
    return mode >= FIRST_PSEUDO_RELOC_MODE &&
319
        mode <= LAST_PSEUDO_RELOC_MODE;
320
  }
321
  static inline bool IsConstructCall(Mode mode) {
322
    return mode == CONSTRUCT_CALL;
323
  }
324
  static inline bool IsCodeTarget(Mode mode) {
325
    return mode <= LAST_CODE_ENUM;
326
  }
327
  static inline bool IsEmbeddedObject(Mode mode) {
328
    return mode == EMBEDDED_OBJECT;
329
  }
330
  static inline bool IsRuntimeEntry(Mode mode) {
331
    return mode == RUNTIME_ENTRY;
332
  }
333
  // Is the relocation mode affected by GC?
334
  static inline bool IsGCRelocMode(Mode mode) {
335
    return mode <= LAST_GCED_ENUM;
336
  }
337
  static inline bool IsJSReturn(Mode mode) {
338
    return mode == JS_RETURN;
339
  }
340
  static inline bool IsComment(Mode mode) {
341
    return mode == COMMENT;
342
  }
343
  static inline bool IsConstPool(Mode mode) {
344
    return mode == CONST_POOL;
345
  }
346
  static inline bool IsPosition(Mode mode) {
347
    return mode == POSITION || mode == STATEMENT_POSITION;
348
  }
349
  static inline bool IsStatementPosition(Mode mode) {
350
    return mode == STATEMENT_POSITION;
351
  }
352
  static inline bool IsExternalReference(Mode mode) {
353
    return mode == EXTERNAL_REFERENCE;
354
  }
355
  static inline bool IsInternalReference(Mode mode) {
356
    return mode == INTERNAL_REFERENCE;
357
  }
358
  static inline bool IsDebugBreakSlot(Mode mode) {
359
    return mode == DEBUG_BREAK_SLOT;
360
  }
361
  static inline bool IsNone(Mode mode) {
362
    return mode == NONE32 || mode == NONE64;
363
  }
364
  static inline bool IsCodeAgeSequence(Mode mode) {
365
    return mode == CODE_AGE_SEQUENCE;
366
  }
367
  static inline int ModeMask(Mode mode) { return 1 << mode; }
368

    
369
  // Accessors
370
  byte* pc() const { return pc_; }
371
  void set_pc(byte* pc) { pc_ = pc; }
372
  Mode rmode() const {  return rmode_; }
373
  intptr_t data() const { return data_; }
374
  double data64() const { return data64_; }
375
  Code* host() const { return host_; }
376

    
377
  // Apply a relocation by delta bytes
378
  INLINE(void apply(intptr_t delta));
379

    
380
  // Is the pointer this relocation info refers to coded like a plain pointer
381
  // or is it strange in some way (e.g. relative or patched into a series of
382
  // instructions).
383
  bool IsCodedSpecially();
384

    
385
  // Read/modify the code target in the branch/call instruction
386
  // this relocation applies to;
387
  // can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
388
  INLINE(Address target_address());
389
  INLINE(void set_target_address(Address target,
390
                                 WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
391
  INLINE(Object* target_object());
392
  INLINE(Handle<Object> target_object_handle(Assembler* origin));
393
  INLINE(Object** target_object_address());
394
  INLINE(void set_target_object(Object* target,
395
                                WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
396
  INLINE(Address target_runtime_entry(Assembler* origin));
397
  INLINE(void set_target_runtime_entry(Address target,
398
                                       WriteBarrierMode mode =
399
                                           UPDATE_WRITE_BARRIER));
400
  INLINE(Cell* target_cell());
401
  INLINE(Handle<Cell> target_cell_handle());
402
  INLINE(void set_target_cell(Cell* cell,
403
                              WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
404
  INLINE(Handle<Object> code_age_stub_handle(Assembler* origin));
405
  INLINE(Code* code_age_stub());
406
  INLINE(void set_code_age_stub(Code* stub));
407

    
408
  // Read the address of the word containing the target_address in an
409
  // instruction stream.  What this means exactly is architecture-independent.
410
  // The only architecture-independent user of this function is the serializer.
411
  // The serializer uses it to find out how many raw bytes of instruction to
412
  // output before the next target.  Architecture-independent code shouldn't
413
  // dereference the pointer it gets back from this.
414
  INLINE(Address target_address_address());
415
  // This indicates how much space a target takes up when deserializing a code
416
  // stream.  For most architectures this is just the size of a pointer.  For
417
  // an instruction like movw/movt where the target bits are mixed into the
418
  // instruction bits the size of the target will be zero, indicating that the
419
  // serializer should not step forwards in memory after a target is resolved
420
  // and written.  In this case the target_address_address function above
421
  // should return the end of the instructions to be patched, allowing the
422
  // deserializer to deserialize the instructions as raw bytes and put them in
423
  // place, ready to be patched with the target.
424
  INLINE(int target_address_size());
425

    
426
  // Read/modify the reference in the instruction this relocation
427
  // applies to; can only be called if rmode_ is external_reference
428
  INLINE(Address* target_reference_address());
429

    
430
  // Read/modify the address of a call instruction. This is used to relocate
431
  // the break points where straight-line code is patched with a call
432
  // instruction.
433
  INLINE(Address call_address());
434
  INLINE(void set_call_address(Address target));
435
  INLINE(Object* call_object());
436
  INLINE(void set_call_object(Object* target));
437
  INLINE(Object** call_object_address());
438

    
439
  template<typename StaticVisitor> inline void Visit(Heap* heap);
440
  inline void Visit(Isolate* isolate, ObjectVisitor* v);
441

    
442
  // Patch the code with some other code.
443
  void PatchCode(byte* instructions, int instruction_count);
444

    
445
  // Patch the code with a call.
446
  void PatchCodeWithCall(Address target, int guard_bytes);
447

    
448
  // Check whether this return sequence has been patched
449
  // with a call to the debugger.
450
  INLINE(bool IsPatchedReturnSequence());
451

    
452
  // Check whether this debug break slot has been patched with a call to the
453
  // debugger.
454
  INLINE(bool IsPatchedDebugBreakSlotSequence());
455

    
456
#ifdef DEBUG
457
  // Check whether the given code contains relocation information that
458
  // either is position-relative or movable by the garbage collector.
459
  static bool RequiresRelocation(const CodeDesc& desc);
460
#endif
461

    
462
#ifdef ENABLE_DISASSEMBLER
463
  // Printing
464
  static const char* RelocModeName(Mode rmode);
465
  void Print(Isolate* isolate, FILE* out);
466
#endif  // ENABLE_DISASSEMBLER
467
#ifdef VERIFY_HEAP
468
  void Verify();
469
#endif
470

    
471
  static const int kCodeTargetMask = (1 << (LAST_CODE_ENUM + 1)) - 1;
472
  static const int kPositionMask = 1 << POSITION | 1 << STATEMENT_POSITION;
473
  static const int kDataMask =
474
      (1 << CODE_TARGET_WITH_ID) | kPositionMask | (1 << COMMENT);
475
  static const int kApplyMask;  // Modes affected by apply. Depends on arch.
476

    
477
 private:
478
  // On ARM, note that pc_ is the address of the constant pool entry
479
  // to be relocated and not the address of the instruction
480
  // referencing the constant pool entry (except when rmode_ ==
481
  // comment).
482
  byte* pc_;
483
  Mode rmode_;
484
  union {
485
    intptr_t data_;
486
    double data64_;
487
  };
488
  Code* host_;
489
  // Code and Embedded Object pointers on some platforms are stored split
490
  // across two consecutive 32-bit instructions. Heap management
491
  // routines expect to access these pointers indirectly. The following
492
  // location provides a place for these pointers to exist naturally
493
  // when accessed via the Iterator.
494
  Object* reconstructed_obj_ptr_;
495
  // External-reference pointers are also split across instruction-pairs
496
  // on some platforms, but are accessed via indirect pointers. This location
497
  // provides a place for that pointer to exist naturally. Its address
498
  // is returned by RelocInfo::target_reference_address().
499
  Address reconstructed_adr_ptr_;
500
  friend class RelocIterator;
501
};
502

    
503

    
504
// RelocInfoWriter serializes a stream of relocation info. It writes towards
505
// lower addresses.
506
class RelocInfoWriter BASE_EMBEDDED {
507
 public:
508
  RelocInfoWriter() : pos_(NULL),
509
                      last_pc_(NULL),
510
                      last_id_(0),
511
                      last_position_(0) {}
512
  RelocInfoWriter(byte* pos, byte* pc) : pos_(pos),
513
                                         last_pc_(pc),
514
                                         last_id_(0),
515
                                         last_position_(0) {}
516

    
517
  byte* pos() const { return pos_; }
518
  byte* last_pc() const { return last_pc_; }
519

    
520
  void Write(const RelocInfo* rinfo);
521

    
522
  // Update the state of the stream after reloc info buffer
523
  // and/or code is moved while the stream is active.
524
  void Reposition(byte* pos, byte* pc) {
525
    pos_ = pos;
526
    last_pc_ = pc;
527
  }
528

    
529
  // Max size (bytes) of a written RelocInfo. Longest encoding is
530
  // ExtraTag, VariableLengthPCJump, ExtraTag, pc_delta, ExtraTag, data_delta.
531
  // On ia32 and arm this is 1 + 4 + 1 + 1 + 1 + 4 = 12.
532
  // On x64 this is 1 + 4 + 1 + 1 + 1 + 8 == 16;
533
  // Here we use the maximum of the two.
534
  static const int kMaxSize = 16;
535

    
536
 private:
537
  inline uint32_t WriteVariableLengthPCJump(uint32_t pc_delta);
538
  inline void WriteTaggedPC(uint32_t pc_delta, int tag);
539
  inline void WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag);
540
  inline void WriteExtraTaggedIntData(int data_delta, int top_tag);
541
  inline void WriteExtraTaggedConstPoolData(int data);
542
  inline void WriteExtraTaggedData(intptr_t data_delta, int top_tag);
543
  inline void WriteTaggedData(intptr_t data_delta, int tag);
544
  inline void WriteExtraTag(int extra_tag, int top_tag);
545

    
546
  byte* pos_;
547
  byte* last_pc_;
548
  int last_id_;
549
  int last_position_;
550
  DISALLOW_COPY_AND_ASSIGN(RelocInfoWriter);
551
};
552

    
553

    
554
// A RelocIterator iterates over relocation information.
555
// Typical use:
556
//
557
//   for (RelocIterator it(code); !it.done(); it.next()) {
558
//     // do something with it.rinfo() here
559
//   }
560
//
561
// A mask can be specified to skip unwanted modes.
562
class RelocIterator: public Malloced {
563
 public:
564
  // Create a new iterator positioned at
565
  // the beginning of the reloc info.
566
  // Relocation information with mode k is included in the
567
  // iteration iff bit k of mode_mask is set.
568
  explicit RelocIterator(Code* code, int mode_mask = -1);
569
  explicit RelocIterator(const CodeDesc& desc, int mode_mask = -1);
570

    
571
  // Iteration
572
  bool done() const { return done_; }
573
  void next();
574

    
575
  // Return pointer valid until next next().
576
  RelocInfo* rinfo() {
577
    ASSERT(!done());
578
    return &rinfo_;
579
  }
580

    
581
 private:
582
  // Advance* moves the position before/after reading.
583
  // *Read* reads from current byte(s) into rinfo_.
584
  // *Get* just reads and returns info on current byte.
585
  void Advance(int bytes = 1) { pos_ -= bytes; }
586
  int AdvanceGetTag();
587
  int GetExtraTag();
588
  int GetTopTag();
589
  void ReadTaggedPC();
590
  void AdvanceReadPC();
591
  void AdvanceReadId();
592
  void AdvanceReadConstPoolData();
593
  void AdvanceReadPosition();
594
  void AdvanceReadData();
595
  void AdvanceReadVariableLengthPCJump();
596
  int GetLocatableTypeTag();
597
  void ReadTaggedId();
598
  void ReadTaggedPosition();
599

    
600
  // If the given mode is wanted, set it in rinfo_ and return true.
601
  // Else return false. Used for efficiently skipping unwanted modes.
602
  bool SetMode(RelocInfo::Mode mode) {
603
    return (mode_mask_ & (1 << mode)) ? (rinfo_.rmode_ = mode, true) : false;
604
  }
605

    
606
  byte* pos_;
607
  byte* end_;
608
  byte* code_age_sequence_;
609
  RelocInfo rinfo_;
610
  bool done_;
611
  int mode_mask_;
612
  int last_id_;
613
  int last_position_;
614
  DISALLOW_COPY_AND_ASSIGN(RelocIterator);
615
};
616

    
617

    
618
//------------------------------------------------------------------------------
619
// External function
620

    
621
//----------------------------------------------------------------------------
622
class IC_Utility;
623
class SCTableReference;
624
#ifdef ENABLE_DEBUGGER_SUPPORT
625
class Debug_Address;
626
#endif
627

    
628

    
629
// An ExternalReference represents a C++ address used in the generated
630
// code. All references to C++ functions and variables must be encapsulated in
631
// an ExternalReference instance. This is done in order to track the origin of
632
// all external references in the code so that they can be bound to the correct
633
// addresses when deserializing a heap.
634
class ExternalReference BASE_EMBEDDED {
635
 public:
636
  // Used in the simulator to support different native api calls.
637
  enum Type {
638
    // Builtin call.
639
    // MaybeObject* f(v8::internal::Arguments).
640
    BUILTIN_CALL,  // default
641

    
642
    // Builtin that takes float arguments and returns an int.
643
    // int f(double, double).
644
    BUILTIN_COMPARE_CALL,
645

    
646
    // Builtin call that returns floating point.
647
    // double f(double, double).
648
    BUILTIN_FP_FP_CALL,
649

    
650
    // Builtin call that returns floating point.
651
    // double f(double).
652
    BUILTIN_FP_CALL,
653

    
654
    // Builtin call that returns floating point.
655
    // double f(double, int).
656
    BUILTIN_FP_INT_CALL,
657

    
658
    // Direct call to API function callback.
659
    // void f(v8::FunctionCallbackInfo&)
660
    DIRECT_API_CALL,
661

    
662
    // Call to function callback via InvokeFunctionCallback.
663
    // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback)
664
    PROFILING_API_CALL,
665

    
666
    // Direct call to accessor getter callback.
667
    // void f(Local<String> property, PropertyCallbackInfo& info)
668
    DIRECT_GETTER_CALL,
669

    
670
    // Call to accessor getter callback via InvokeAccessorGetterCallback.
671
    // void f(Local<String> property, PropertyCallbackInfo& info,
672
    //     AccessorGetterCallback callback)
673
    PROFILING_GETTER_CALL
674
  };
675

    
676
  static void SetUp();
677
  static void InitializeMathExpData();
678
  static void TearDownMathExpData();
679

    
680
  typedef void* ExternalReferenceRedirector(void* original, Type type);
681

    
682
  ExternalReference() : address_(NULL) {}
683

    
684
  ExternalReference(Builtins::CFunctionId id, Isolate* isolate);
685

    
686
  ExternalReference(ApiFunction* ptr, Type type, Isolate* isolate);
687

    
688
  ExternalReference(Builtins::Name name, Isolate* isolate);
689

    
690
  ExternalReference(Runtime::FunctionId id, Isolate* isolate);
691

    
692
  ExternalReference(const Runtime::Function* f, Isolate* isolate);
693

    
694
  ExternalReference(const IC_Utility& ic_utility, Isolate* isolate);
695

    
696
#ifdef ENABLE_DEBUGGER_SUPPORT
697
  ExternalReference(const Debug_Address& debug_address, Isolate* isolate);
698
#endif
699

    
700
  explicit ExternalReference(StatsCounter* counter);
701

    
702
  ExternalReference(Isolate::AddressId id, Isolate* isolate);
703

    
704
  explicit ExternalReference(const SCTableReference& table_ref);
705

    
706
  // Isolate as an external reference.
707
  static ExternalReference isolate_address(Isolate* isolate);
708

    
709
  // One-of-a-kind references. These references are not part of a general
710
  // pattern. This means that they have to be added to the
711
  // ExternalReferenceTable in serialize.cc manually.
712

    
713
  static ExternalReference incremental_marking_record_write_function(
714
      Isolate* isolate);
715
  static ExternalReference incremental_evacuation_record_write_function(
716
      Isolate* isolate);
717
  static ExternalReference store_buffer_overflow_function(
718
      Isolate* isolate);
719
  static ExternalReference flush_icache_function(Isolate* isolate);
720
  static ExternalReference perform_gc_function(Isolate* isolate);
721
  static ExternalReference fill_heap_number_with_random_function(
722
      Isolate* isolate);
723
  static ExternalReference random_uint32_function(Isolate* isolate);
724
  static ExternalReference transcendental_cache_array_address(Isolate* isolate);
725
  static ExternalReference delete_handle_scope_extensions(Isolate* isolate);
726

    
727
  static ExternalReference get_date_field_function(Isolate* isolate);
728
  static ExternalReference date_cache_stamp(Isolate* isolate);
729

    
730
  static ExternalReference get_make_code_young_function(Isolate* isolate);
731
  static ExternalReference get_mark_code_as_executed_function(Isolate* isolate);
732

    
733
  // New heap objects tracking support.
734
  static ExternalReference record_object_allocation_function(Isolate* isolate);
735

    
736
  // Deoptimization support.
737
  static ExternalReference new_deoptimizer_function(Isolate* isolate);
738
  static ExternalReference compute_output_frames_function(Isolate* isolate);
739

    
740
  // Log support.
741
  static ExternalReference log_enter_external_function(Isolate* isolate);
742
  static ExternalReference log_leave_external_function(Isolate* isolate);
743

    
744
  // Static data in the keyed lookup cache.
745
  static ExternalReference keyed_lookup_cache_keys(Isolate* isolate);
746
  static ExternalReference keyed_lookup_cache_field_offsets(Isolate* isolate);
747

    
748
  // Static variable Heap::roots_array_start()
749
  static ExternalReference roots_array_start(Isolate* isolate);
750

    
751
  // Static variable Heap::allocation_sites_list_address()
752
  static ExternalReference allocation_sites_list_address(Isolate* isolate);
753

    
754
  // Static variable StackGuard::address_of_jslimit()
755
  static ExternalReference address_of_stack_limit(Isolate* isolate);
756

    
757
  // Static variable StackGuard::address_of_real_jslimit()
758
  static ExternalReference address_of_real_stack_limit(Isolate* isolate);
759

    
760
  // Static variable RegExpStack::limit_address()
761
  static ExternalReference address_of_regexp_stack_limit(Isolate* isolate);
762

    
763
  // Static variables for RegExp.
764
  static ExternalReference address_of_static_offsets_vector(Isolate* isolate);
765
  static ExternalReference address_of_regexp_stack_memory_address(
766
      Isolate* isolate);
767
  static ExternalReference address_of_regexp_stack_memory_size(
768
      Isolate* isolate);
769

    
770
  // Static variable Heap::NewSpaceStart()
771
  static ExternalReference new_space_start(Isolate* isolate);
772
  static ExternalReference new_space_mask(Isolate* isolate);
773
  static ExternalReference heap_always_allocate_scope_depth(Isolate* isolate);
774
  static ExternalReference new_space_mark_bits(Isolate* isolate);
775

    
776
  // Write barrier.
777
  static ExternalReference store_buffer_top(Isolate* isolate);
778

    
779
  // Used for fast allocation in generated code.
780
  static ExternalReference new_space_allocation_top_address(Isolate* isolate);
781
  static ExternalReference new_space_allocation_limit_address(Isolate* isolate);
782
  static ExternalReference old_pointer_space_allocation_top_address(
783
      Isolate* isolate);
784
  static ExternalReference old_pointer_space_allocation_limit_address(
785
      Isolate* isolate);
786
  static ExternalReference old_data_space_allocation_top_address(
787
      Isolate* isolate);
788
  static ExternalReference old_data_space_allocation_limit_address(
789
      Isolate* isolate);
790
  static ExternalReference new_space_high_promotion_mode_active_address(
791
      Isolate* isolate);
792

    
793
  static ExternalReference double_fp_operation(Token::Value operation,
794
                                               Isolate* isolate);
795
  static ExternalReference compare_doubles(Isolate* isolate);
796
  static ExternalReference power_double_double_function(Isolate* isolate);
797
  static ExternalReference power_double_int_function(Isolate* isolate);
798

    
799
  static ExternalReference handle_scope_next_address(Isolate* isolate);
800
  static ExternalReference handle_scope_limit_address(Isolate* isolate);
801
  static ExternalReference handle_scope_level_address(Isolate* isolate);
802

    
803
  static ExternalReference scheduled_exception_address(Isolate* isolate);
804
  static ExternalReference address_of_pending_message_obj(Isolate* isolate);
805
  static ExternalReference address_of_has_pending_message(Isolate* isolate);
806
  static ExternalReference address_of_pending_message_script(Isolate* isolate);
807

    
808
  // Static variables containing common double constants.
809
  static ExternalReference address_of_min_int();
810
  static ExternalReference address_of_one_half();
811
  static ExternalReference address_of_minus_one_half();
812
  static ExternalReference address_of_minus_zero();
813
  static ExternalReference address_of_zero();
814
  static ExternalReference address_of_uint8_max_value();
815
  static ExternalReference address_of_negative_infinity();
816
  static ExternalReference address_of_canonical_non_hole_nan();
817
  static ExternalReference address_of_the_hole_nan();
818
  static ExternalReference address_of_uint32_bias();
819

    
820
  static ExternalReference math_sin_double_function(Isolate* isolate);
821
  static ExternalReference math_cos_double_function(Isolate* isolate);
822
  static ExternalReference math_tan_double_function(Isolate* isolate);
823
  static ExternalReference math_log_double_function(Isolate* isolate);
824

    
825
  static ExternalReference math_exp_constants(int constant_index);
826
  static ExternalReference math_exp_log_table();
827

    
828
  static ExternalReference page_flags(Page* page);
829

    
830
  static ExternalReference ForDeoptEntry(Address entry);
831

    
832
  static ExternalReference cpu_features();
833

    
834
  Address address() const { return reinterpret_cast<Address>(address_); }
835

    
836
#ifdef ENABLE_DEBUGGER_SUPPORT
837
  // Function Debug::Break()
838
  static ExternalReference debug_break(Isolate* isolate);
839

    
840
  // Used to check if single stepping is enabled in generated code.
841
  static ExternalReference debug_step_in_fp_address(Isolate* isolate);
842
#endif
843

    
844
#ifndef V8_INTERPRETED_REGEXP
845
  // C functions called from RegExp generated code.
846

    
847
  // Function NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()
848
  static ExternalReference re_case_insensitive_compare_uc16(Isolate* isolate);
849

    
850
  // Function RegExpMacroAssembler*::CheckStackGuardState()
851
  static ExternalReference re_check_stack_guard_state(Isolate* isolate);
852

    
853
  // Function NativeRegExpMacroAssembler::GrowStack()
854
  static ExternalReference re_grow_stack(Isolate* isolate);
855

    
856
  // byte NativeRegExpMacroAssembler::word_character_bitmap
857
  static ExternalReference re_word_character_map();
858

    
859
#endif
860

    
861
  // This lets you register a function that rewrites all external references.
862
  // Used by the ARM simulator to catch calls to external references.
863
  static void set_redirector(Isolate* isolate,
864
                             ExternalReferenceRedirector* redirector) {
865
    // We can't stack them.
866
    ASSERT(isolate->external_reference_redirector() == NULL);
867
    isolate->set_external_reference_redirector(
868
        reinterpret_cast<ExternalReferenceRedirectorPointer*>(redirector));
869
  }
870

    
871
  static ExternalReference stress_deopt_count(Isolate* isolate);
872

    
873
  bool operator==(const ExternalReference& other) const {
874
    return address_ == other.address_;
875
  }
876

    
877
  bool operator!=(const ExternalReference& other) const {
878
    return !(*this == other);
879
  }
880

    
881
 private:
882
  explicit ExternalReference(void* address)
883
      : address_(address) {}
884

    
885
  static void* Redirect(Isolate* isolate,
886
                        void* address,
887
                        Type type = ExternalReference::BUILTIN_CALL) {
888
    ExternalReferenceRedirector* redirector =
889
        reinterpret_cast<ExternalReferenceRedirector*>(
890
            isolate->external_reference_redirector());
891
    if (redirector == NULL) return address;
892
    void* answer = (*redirector)(address, type);
893
    return answer;
894
  }
895

    
896
  static void* Redirect(Isolate* isolate,
897
                        Address address_arg,
898
                        Type type = ExternalReference::BUILTIN_CALL) {
899
    ExternalReferenceRedirector* redirector =
900
        reinterpret_cast<ExternalReferenceRedirector*>(
901
            isolate->external_reference_redirector());
902
    void* address = reinterpret_cast<void*>(address_arg);
903
    void* answer = (redirector == NULL) ?
904
                   address :
905
                   (*redirector)(address, type);
906
    return answer;
907
  }
908

    
909
  void* address_;
910
};
911

    
912

    
913
// -----------------------------------------------------------------------------
914
// Position recording support
915

    
916
struct PositionState {
917
  PositionState() : current_position(RelocInfo::kNoPosition),
918
                    written_position(RelocInfo::kNoPosition),
919
                    current_statement_position(RelocInfo::kNoPosition),
920
                    written_statement_position(RelocInfo::kNoPosition) {}
921

    
922
  int current_position;
923
  int written_position;
924

    
925
  int current_statement_position;
926
  int written_statement_position;
927
};
928

    
929

    
930
class PositionsRecorder BASE_EMBEDDED {
931
 public:
932
  explicit PositionsRecorder(Assembler* assembler)
933
      : assembler_(assembler) {
934
#ifdef ENABLE_GDB_JIT_INTERFACE
935
    gdbjit_lineinfo_ = NULL;
936
#endif
937
    jit_handler_data_ = NULL;
938
  }
939

    
940
#ifdef ENABLE_GDB_JIT_INTERFACE
941
  ~PositionsRecorder() {
942
    delete gdbjit_lineinfo_;
943
  }
944

    
945
  void StartGDBJITLineInfoRecording() {
946
    if (FLAG_gdbjit) {
947
      gdbjit_lineinfo_ = new GDBJITLineInfo();
948
    }
949
  }
950

    
951
  GDBJITLineInfo* DetachGDBJITLineInfo() {
952
    GDBJITLineInfo* lineinfo = gdbjit_lineinfo_;
953
    gdbjit_lineinfo_ = NULL;  // To prevent deallocation in destructor.
954
    return lineinfo;
955
  }
956
#endif
957
  void AttachJITHandlerData(void* user_data) {
958
    jit_handler_data_ = user_data;
959
  }
960

    
961
  void* DetachJITHandlerData() {
962
    void* old_data = jit_handler_data_;
963
    jit_handler_data_ = NULL;
964
    return old_data;
965
  }
966
  // Set current position to pos.
967
  void RecordPosition(int pos);
968

    
969
  // Set current statement position to pos.
970
  void RecordStatementPosition(int pos);
971

    
972
  // Write recorded positions to relocation information.
973
  bool WriteRecordedPositions();
974

    
975
  int current_position() const { return state_.current_position; }
976

    
977
  int current_statement_position() const {
978
    return state_.current_statement_position;
979
  }
980

    
981
 private:
982
  Assembler* assembler_;
983
  PositionState state_;
984
#ifdef ENABLE_GDB_JIT_INTERFACE
985
  GDBJITLineInfo* gdbjit_lineinfo_;
986
#endif
987

    
988
  // Currently jit_handler_data_ is used to store JITHandler-specific data
989
  // over the lifetime of a PositionsRecorder
990
  void* jit_handler_data_;
991
  friend class PreservePositionScope;
992

    
993
  DISALLOW_COPY_AND_ASSIGN(PositionsRecorder);
994
};
995

    
996

    
997
class PreservePositionScope BASE_EMBEDDED {
998
 public:
999
  explicit PreservePositionScope(PositionsRecorder* positions_recorder)
1000
      : positions_recorder_(positions_recorder),
1001
        saved_state_(positions_recorder->state_) {}
1002

    
1003
  ~PreservePositionScope() {
1004
    positions_recorder_->state_ = saved_state_;
1005
  }
1006

    
1007
 private:
1008
  PositionsRecorder* positions_recorder_;
1009
  const PositionState saved_state_;
1010

    
1011
  DISALLOW_COPY_AND_ASSIGN(PreservePositionScope);
1012
};
1013

    
1014

    
1015
// -----------------------------------------------------------------------------
1016
// Utility functions
1017

    
1018
inline bool is_intn(int x, int n)  {
1019
  return -(1 << (n-1)) <= x && x < (1 << (n-1));
1020
}
1021

    
1022
inline bool is_int8(int x)  { return is_intn(x, 8); }
1023
inline bool is_int16(int x)  { return is_intn(x, 16); }
1024
inline bool is_int18(int x)  { return is_intn(x, 18); }
1025
inline bool is_int24(int x)  { return is_intn(x, 24); }
1026

    
1027
inline bool is_uintn(int x, int n) {
1028
  return (x & -(1 << n)) == 0;
1029
}
1030

    
1031
inline bool is_uint2(int x)  { return is_uintn(x, 2); }
1032
inline bool is_uint3(int x)  { return is_uintn(x, 3); }
1033
inline bool is_uint4(int x)  { return is_uintn(x, 4); }
1034
inline bool is_uint5(int x)  { return is_uintn(x, 5); }
1035
inline bool is_uint6(int x)  { return is_uintn(x, 6); }
1036
inline bool is_uint8(int x)  { return is_uintn(x, 8); }
1037
inline bool is_uint10(int x)  { return is_uintn(x, 10); }
1038
inline bool is_uint12(int x)  { return is_uintn(x, 12); }
1039
inline bool is_uint16(int x)  { return is_uintn(x, 16); }
1040
inline bool is_uint24(int x)  { return is_uintn(x, 24); }
1041
inline bool is_uint26(int x)  { return is_uintn(x, 26); }
1042
inline bool is_uint28(int x)  { return is_uintn(x, 28); }
1043

    
1044
inline int NumberOfBitsSet(uint32_t x) {
1045
  unsigned int num_bits_set;
1046
  for (num_bits_set = 0; x; x >>= 1) {
1047
    num_bits_set += x & 1;
1048
  }
1049
  return num_bits_set;
1050
}
1051

    
1052
bool EvalComparison(Token::Value op, double op1, double op2);
1053

    
1054
// Computes pow(x, y) with the special cases in the spec for Math.pow.
1055
double power_helper(double x, double y);
1056
double power_double_int(double x, int y);
1057
double power_double_double(double x, double y);
1058

    
1059
// Helper class for generating code or data associated with the code
1060
// right after a call instruction. As an example this can be used to
1061
// generate safepoint data after calls for crankshaft.
1062
class CallWrapper {
1063
 public:
1064
  CallWrapper() { }
1065
  virtual ~CallWrapper() { }
1066
  // Called just before emitting a call. Argument is the size of the generated
1067
  // call code.
1068
  virtual void BeforeCall(int call_size) const = 0;
1069
  // Called just after emitting a call, i.e., at the return site for the call.
1070
  virtual void AfterCall() const = 0;
1071
};
1072

    
1073
class NullCallWrapper : public CallWrapper {
1074
 public:
1075
  NullCallWrapper() { }
1076
  virtual ~NullCallWrapper() { }
1077
  virtual void BeforeCall(int call_size) const { }
1078
  virtual void AfterCall() const { }
1079
};
1080

    
1081
} }  // namespace v8::internal
1082

    
1083
#endif  // V8_ASSEMBLER_H_