V8 Project
instruction.h
Go to the documentation of this file.
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_COMPILER_INSTRUCTION_H_
6 #define V8_COMPILER_INSTRUCTION_H_
7 
8 #include <deque>
9 #include <map>
10 #include <set>
11 
13 #include "src/compiler/frame.h"
14 #include "src/compiler/graph.h"
16 #include "src/compiler/opcodes.h"
17 #include "src/compiler/schedule.h"
18 // TODO(titzer): don't include the macro-assembler?
19 #include "src/macro-assembler.h"
20 #include "src/zone-allocator.h"
21 
22 namespace v8 {
23 namespace internal {
24 
25 // Forward declarations.
26 class OStream;
27 
28 namespace compiler {
29 
30 // Forward declarations.
31 class Linkage;
32 
33 // A couple of reserved opcodes are used for internal use.
37 
38 
39 #define INSTRUCTION_OPERAND_LIST(V) \
40  V(Constant, CONSTANT, 128) \
41  V(Immediate, IMMEDIATE, 128) \
42  V(StackSlot, STACK_SLOT, 128) \
43  V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \
44  V(Register, REGISTER, Register::kNumRegisters) \
45  V(DoubleRegister, DOUBLE_REGISTER, DoubleRegister::kMaxNumRegisters)
46 
48  public:
49  enum Kind {
58  };
59 
62 
63  Kind kind() const { return KindField::decode(value_); }
64  int index() const { return static_cast<int>(value_) >> KindField::kSize; }
65 #define INSTRUCTION_OPERAND_PREDICATE(name, type, number) \
66  bool Is##name() const { return kind() == type; }
70 #undef INSTRUCTION_OPERAND_PREDICATE
71  bool Equals(InstructionOperand* other) const {
72  return value_ == other->value_;
73  }
74 
75  void ConvertTo(Kind kind, int index) {
76  if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0);
79  DCHECK(this->index() == index);
80  }
81 
82  // Calls SetUpCache()/TearDownCache() for each subclass.
83  static void SetUpCaches();
84  static void TearDownCaches();
85 
86  protected:
88 
89  unsigned value_;
90 };
91 
93 
95 
97  public:
99 
107  };
108 
109  // Lifetime of operand inside the instruction.
110  enum Lifetime {
111  // USED_AT_START operand is guaranteed to be live only at
112  // instruction start. Register allocator is free to assign the same register
113  // to some other operand used inside instruction (i.e. temporary or
114  // output).
116 
117  // USED_AT_END operand is treated as live until the end of
118  // instruction. This means that register allocator will not reuse it's
119  // register for any other operand inside instruction.
121  };
122 
128  }
129 
132  DCHECK(policy == FIXED_SLOT);
133  value_ |= BasicPolicyField::encode(policy);
135  DCHECK(this->fixed_slot_index() == index);
136  }
137 
140  DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER);
145  }
146 
151  value_ |= LifetimeField::encode(lifetime);
152  }
153 
155  UnallocatedOperand* result = new (zone) UnallocatedOperand(ANY);
157  return result;
158  }
159 
160  static const UnallocatedOperand* cast(const InstructionOperand* op) {
161  DCHECK(op->IsUnallocated());
162  return static_cast<const UnallocatedOperand*>(op);
163  }
164 
166  DCHECK(op->IsUnallocated());
167  return static_cast<UnallocatedOperand*>(op);
168  }
169 
170  // The encoding used for UnallocatedOperand operands depends on the policy
171  // that is
172  // stored within the operand. The FIXED_SLOT policy uses a compact encoding
173  // because it accommodates a larger pay-load.
174  //
175  // For FIXED_SLOT policy:
176  // +------------------------------------------+
177  // | slot_index | vreg | 0 | 001 |
178  // +------------------------------------------+
179  //
180  // For all other (extended) policies:
181  // +------------------------------------------+
182  // | reg_index | L | PPP | vreg | 1 | 001 | L ... Lifetime
183  // +------------------------------------------+ P ... Policy
184  //
185  // The slot index is a signed value which requires us to decode it manually
186  // instead of using the BitField utility class.
187 
188  // The superclass has a KindField.
190 
191  // BitFields for all unallocated operands.
192  class BasicPolicyField : public BitField<BasicPolicy, 3, 1> {};
193  class VirtualRegisterField : public BitField<unsigned, 4, 18> {};
194 
195  // BitFields specific to BasicPolicy::FIXED_SLOT.
196  class FixedSlotIndexField : public BitField<int, 22, 10> {};
197 
198  // BitFields specific to BasicPolicy::EXTENDED_POLICY.
199  class ExtendedPolicyField : public BitField<ExtendedPolicy, 22, 3> {};
200  class LifetimeField : public BitField<Lifetime, 25, 1> {};
201  class FixedRegisterField : public BitField<int, 26, 6> {};
202 
205  static const int kMaxFixedSlotIndex = (1 << (kFixedSlotIndexWidth - 1)) - 1;
206  static const int kMinFixedSlotIndex = -(1 << (kFixedSlotIndexWidth - 1));
207 
208  // Predicates for the operand policy.
209  bool HasAnyPolicy() const {
210  return basic_policy() == EXTENDED_POLICY && extended_policy() == ANY;
211  }
212  bool HasFixedPolicy() const {
213  return basic_policy() == FIXED_SLOT ||
216  }
217  bool HasRegisterPolicy() const {
218  return basic_policy() == EXTENDED_POLICY &&
220  }
221  bool HasSameAsInputPolicy() const {
222  return basic_policy() == EXTENDED_POLICY &&
224  }
225  bool HasFixedSlotPolicy() const { return basic_policy() == FIXED_SLOT; }
226  bool HasFixedRegisterPolicy() const {
227  return basic_policy() == EXTENDED_POLICY &&
229  }
231  return basic_policy() == EXTENDED_POLICY &&
233  }
234 
235  // [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
237 
238  // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
242  }
243 
244  // [fixed_slot_index]: Only for FIXED_SLOT.
245  int fixed_slot_index() const {
247  return static_cast<int>(value_) >> FixedSlotIndexField::kShift;
248  }
249 
250  // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER.
251  int fixed_register_index() const {
254  }
255 
256  // [virtual_register]: The virtual register ID for this operand.
258  void set_virtual_register(unsigned id) {
260  }
261 
262  // [lifetime]: Only for non-FIXED_SLOT.
263  bool IsUsedAtStart() {
266  }
267 };
268 
269 
270 class MoveOperands FINAL {
271  public:
273  : source_(source), destination_(destination) {}
274 
275  InstructionOperand* source() const { return source_; }
276  void set_source(InstructionOperand* operand) { source_ = operand; }
277 
278  InstructionOperand* destination() const { return destination_; }
279  void set_destination(InstructionOperand* operand) { destination_ = operand; }
280 
281  // The gap resolver marks moves as "in-progress" by clearing the
282  // destination (but not the source).
283  bool IsPending() const { return destination_ == NULL && source_ != NULL; }
284 
285  // True if this move a move into the given destination operand.
286  bool Blocks(InstructionOperand* operand) const {
287  return !IsEliminated() && source()->Equals(operand);
288  }
289 
290  // A move is redundant if it's been eliminated, if its source and
291  // destination are the same, or if its destination is unneeded or constant.
292  bool IsRedundant() const {
293  return IsEliminated() || source_->Equals(destination_) || IsIgnored() ||
294  (destination_ != NULL && destination_->IsConstant());
295  }
296 
297  bool IsIgnored() const {
298  return destination_ != NULL && destination_->IsIgnored();
299  }
300 
301  // We clear both operands to indicate move that's been eliminated.
302  void Eliminate() { source_ = destination_ = NULL; }
303  bool IsEliminated() const {
304  DCHECK(source_ != NULL || destination_ == NULL);
305  return source_ == NULL;
306  }
307 
308  private:
311 };
312 
313 OStream& operator<<(OStream& os, const MoveOperands& mo);
314 
315 template <InstructionOperand::Kind kOperandKind, int kNumCachedOperands>
316 class SubKindOperand FINAL : public InstructionOperand {
317  public:
318  static SubKindOperand* Create(int index, Zone* zone) {
319  DCHECK(index >= 0);
320  if (index < kNumCachedOperands) return &cache[index];
321  return new (zone) SubKindOperand(index);
322  }
323 
324  static SubKindOperand* cast(InstructionOperand* op) {
325  DCHECK(op->kind() == kOperandKind);
326  return reinterpret_cast<SubKindOperand*>(op);
327  }
328 
329  static void SetUpCache();
330  static void TearDownCache();
331 
332  private:
333  static SubKindOperand* cache;
334 
336  explicit SubKindOperand(int index)
337  : InstructionOperand(kOperandKind, index) {}
338 };
339 
340 
341 #define INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS(name, type, number) \
342  typedef SubKindOperand<InstructionOperand::type, number> name##Operand;
344 #undef INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS
345 
346 
347 class ParallelMove FINAL : public ZoneObject {
348  public:
349  explicit ParallelMove(Zone* zone) : move_operands_(4, zone) {}
350 
352  move_operands_.Add(MoveOperands(from, to), zone);
353  }
354 
355  bool IsRedundant() const;
356 
357  ZoneList<MoveOperands>* move_operands() { return &move_operands_; }
359  return &move_operands_;
360  }
361 
362  private:
364 };
365 
366 OStream& operator<<(OStream& os, const ParallelMove& pm);
367 
368 class PointerMap FINAL : public ZoneObject {
369  public:
370  explicit PointerMap(Zone* zone)
371  : pointer_operands_(8, zone),
372  untagged_operands_(0, zone),
373  instruction_position_(-1) {}
374 
376  for (int i = 0; i < untagged_operands_.length(); ++i) {
377  RemovePointer(untagged_operands_[i]);
378  }
379  untagged_operands_.Clear();
380  return &pointer_operands_;
381  }
382  int instruction_position() const { return instruction_position_; }
383 
384  void set_instruction_position(int pos) {
385  DCHECK(instruction_position_ == -1);
386  instruction_position_ = pos;
387  }
388 
392 
393  private:
394  friend OStream& operator<<(OStream& os, const PointerMap& pm);
395 
399 };
400 
401 OStream& operator<<(OStream& os, const PointerMap& pm);
402 
403 // TODO(titzer): s/PointerMap/ReferenceMap/
404 class Instruction : public ZoneObject {
405  public:
406  size_t OutputCount() const { return OutputCountField::decode(bit_field_); }
407  InstructionOperand* OutputAt(size_t i) const {
408  DCHECK(i < OutputCount());
409  return operands_[i];
410  }
411 
412  bool HasOutput() const { return OutputCount() == 1; }
413  InstructionOperand* Output() const { return OutputAt(0); }
414 
415  size_t InputCount() const { return InputCountField::decode(bit_field_); }
416  InstructionOperand* InputAt(size_t i) const {
417  DCHECK(i < InputCount());
418  return operands_[OutputCount() + i];
419  }
420 
421  size_t TempCount() const { return TempCountField::decode(bit_field_); }
422  InstructionOperand* TempAt(size_t i) const {
423  DCHECK(i < TempCount());
424  return operands_[OutputCount() + InputCount() + i];
425  }
426 
427  InstructionCode opcode() const { return opcode_; }
431  }
435  }
436 
437  // TODO(titzer): make control and call into flags.
439  return New(zone, opcode, 0, NULL, 0, NULL, 0, NULL);
440  }
441 
443  size_t output_count, InstructionOperand** outputs,
444  size_t input_count, InstructionOperand** inputs,
445  size_t temp_count, InstructionOperand** temps) {
446  DCHECK(opcode >= 0);
447  DCHECK(output_count == 0 || outputs != NULL);
448  DCHECK(input_count == 0 || inputs != NULL);
449  DCHECK(temp_count == 0 || temps != NULL);
450  InstructionOperand* none = NULL;
451  USE(none);
452  int size = static_cast<int>(RoundUp(sizeof(Instruction), kPointerSize) +
453  (output_count + input_count + temp_count - 1) *
454  sizeof(none));
455  return new (zone->New(size)) Instruction(
456  opcode, output_count, outputs, input_count, inputs, temp_count, temps);
457  }
458 
459  // TODO(titzer): another holdover from lithium days; register allocator
460  // should not need to know about control instructions.
463  return this;
464  }
467  return this;
468  }
469  bool IsControl() const { return IsControlField::decode(bit_field_); }
470  bool IsCall() const { return IsCallField::decode(bit_field_); }
471  bool NeedsPointerMap() const { return IsCall(); }
472  bool HasPointerMap() const { return pointer_map_ != NULL; }
473 
474  bool IsGapMoves() const {
476  }
477  bool IsBlockStart() const { return opcode() == kBlockStartInstruction; }
478  bool IsSourcePosition() const {
480  }
481 
482  bool ClobbersRegisters() const { return IsCall(); }
483  bool ClobbersTemps() const { return IsCall(); }
484  bool ClobbersDoubleRegisters() const { return IsCall(); }
485  PointerMap* pointer_map() const { return pointer_map_; }
486 
487  void set_pointer_map(PointerMap* map) {
490  pointer_map_ = map;
491  }
492 
493  // Placement new operator so that we can smash instructions into
494  // zone-allocated memory.
495  void* operator new(size_t, void* location) { return location; }
496 
497  void operator delete(void* pointer, void* location) { UNREACHABLE(); }
498 
499  protected:
501  : opcode_(opcode),
502  bit_field_(OutputCountField::encode(0) | InputCountField::encode(0) |
503  TempCountField::encode(0) | IsCallField::encode(false) |
504  IsControlField::encode(false)),
505  pointer_map_(NULL) {}
506 
507  Instruction(InstructionCode opcode, size_t output_count,
508  InstructionOperand** outputs, size_t input_count,
509  InstructionOperand** inputs, size_t temp_count,
510  InstructionOperand** temps)
511  : opcode_(opcode),
512  bit_field_(OutputCountField::encode(output_count) |
513  InputCountField::encode(input_count) |
514  TempCountField::encode(temp_count) |
515  IsCallField::encode(false) | IsControlField::encode(false)),
516  pointer_map_(NULL) {
517  for (size_t i = 0; i < output_count; ++i) {
518  operands_[i] = outputs[i];
519  }
520  for (size_t i = 0; i < input_count; ++i) {
521  operands_[output_count + i] = inputs[i];
522  }
523  for (size_t i = 0; i < temp_count; ++i) {
524  operands_[output_count + input_count + i] = temps[i];
525  }
526  }
527 
528  protected:
534 
537  PointerMap* pointer_map_;
539 };
540 
541 OStream& operator<<(OStream& os, const Instruction& instr);
542 
543 // Represents moves inserted before an instruction due to register allocation.
544 // TODO(titzer): squash GapInstruction back into Instruction, since essentially
545 // every instruction can possibly have moves inserted before it.
546 class GapInstruction : public Instruction {
547  public:
555  };
556 
557  ParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone) {
558  if (parallel_moves_[pos] == NULL) {
559  parallel_moves_[pos] = new (zone) ParallelMove(zone);
560  }
561  return parallel_moves_[pos];
562  }
563 
564  ParallelMove* GetParallelMove(InnerPosition pos) {
565  return parallel_moves_[pos];
566  }
567 
568  static GapInstruction* New(Zone* zone) {
569  void* buffer = zone->New(sizeof(GapInstruction));
570  return new (buffer) GapInstruction(kGapInstruction);
571  }
572 
573  static GapInstruction* cast(Instruction* instr) {
574  DCHECK(instr->IsGapMoves());
575  return static_cast<GapInstruction*>(instr);
576  }
577 
578  static const GapInstruction* cast(const Instruction* instr) {
579  DCHECK(instr->IsGapMoves());
580  return static_cast<const GapInstruction*>(instr);
581  }
582 
583  protected:
589  }
590 
591  private:
592  friend OStream& operator<<(OStream& os, const Instruction& instr);
594 };
595 
596 
597 // This special kind of gap move instruction represents the beginning of a
598 // block of code.
599 // TODO(titzer): move code_start and code_end from BasicBlock to here.
600 class BlockStartInstruction FINAL : public GapInstruction {
601  public:
602  BasicBlock* block() const { return block_; }
603  Label* label() { return &label_; }
604 
605  static BlockStartInstruction* New(Zone* zone, BasicBlock* block) {
606  void* buffer = zone->New(sizeof(BlockStartInstruction));
607  return new (buffer) BlockStartInstruction(block);
608  }
609 
610  static BlockStartInstruction* cast(Instruction* instr) {
611  DCHECK(instr->IsBlockStart());
612  return static_cast<BlockStartInstruction*>(instr);
613  }
614 
615  private:
616  explicit BlockStartInstruction(BasicBlock* block)
617  : GapInstruction(kBlockStartInstruction), block_(block) {}
618 
619  BasicBlock* block_;
620  Label label_;
621 };
622 
623 
624 class SourcePositionInstruction FINAL : public Instruction {
625  public:
626  static SourcePositionInstruction* New(Zone* zone, SourcePosition position) {
627  void* buffer = zone->New(sizeof(SourcePositionInstruction));
628  return new (buffer) SourcePositionInstruction(position);
629  }
630 
631  SourcePosition source_position() const { return source_position_; }
632 
633  static SourcePositionInstruction* cast(Instruction* instr) {
634  DCHECK(instr->IsSourcePosition());
635  return static_cast<SourcePositionInstruction*>(instr);
636  }
637 
638  static const SourcePositionInstruction* cast(const Instruction* instr) {
639  DCHECK(instr->IsSourcePosition());
640  return static_cast<const SourcePositionInstruction*>(instr);
641  }
642 
643  private:
644  explicit SourcePositionInstruction(SourcePosition source_position)
646  source_position_(source_position) {
647  DCHECK(!source_position_.IsInvalid());
648  DCHECK(!source_position_.IsUnknown());
649  }
650 
651  SourcePosition source_position_;
652 };
653 
654 
655 class Constant FINAL {
656  public:
657  enum Type {
663  kHeapObject
664  };
665 
666  explicit Constant(int32_t v) : type_(kInt32), value_(v) {}
667  explicit Constant(int64_t v) : type_(kInt64), value_(v) {}
668  explicit Constant(float v) : type_(kFloat32), value_(bit_cast<int32_t>(v)) {}
669  explicit Constant(double v) : type_(kFloat64), value_(bit_cast<int64_t>(v)) {}
670  explicit Constant(ExternalReference ref)
671  : type_(kExternalReference), value_(bit_cast<intptr_t>(ref)) {}
673  : type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {}
674 
675  Type type() const { return type_; }
676 
677  int32_t ToInt32() const {
678  DCHECK_EQ(kInt32, type());
679  return static_cast<int32_t>(value_);
680  }
681 
682  int64_t ToInt64() const {
683  if (type() == kInt32) return ToInt32();
684  DCHECK_EQ(kInt64, type());
685  return value_;
686  }
687 
688  float ToFloat32() const {
689  DCHECK_EQ(kFloat32, type());
690  return bit_cast<float>(static_cast<int32_t>(value_));
691  }
692 
693  double ToFloat64() const {
694  if (type() == kInt32) return ToInt32();
695  DCHECK_EQ(kFloat64, type());
696  return bit_cast<double>(value_);
697  }
698 
699  ExternalReference ToExternalReference() const {
700  DCHECK_EQ(kExternalReference, type());
701  return bit_cast<ExternalReference>(static_cast<intptr_t>(value_));
702  }
703 
705  DCHECK_EQ(kHeapObject, type());
706  return bit_cast<Handle<HeapObject> >(static_cast<intptr_t>(value_));
707  }
708 
709  private:
711  int64_t value_;
712 };
713 
714 
716  public:
717  FrameStateDescriptor(const FrameStateCallInfo& state_info,
718  size_t parameters_count, size_t locals_count,
719  size_t stack_count,
721  : type_(state_info.type()),
722  bailout_id_(state_info.bailout_id()),
723  frame_state_combine_(state_info.state_combine()),
728  jsfunction_(state_info.jsfunction()) {}
729 
730  FrameStateType type() const { return type_; }
731  BailoutId bailout_id() const { return bailout_id_; }
733  size_t parameters_count() const { return parameters_count_; }
734  size_t locals_count() const { return locals_count_; }
735  size_t stack_count() const { return stack_count_; }
738 
739  size_t size() const {
741  (HasContext() ? 1 : 0);
742  }
743 
744  size_t GetTotalSize() const {
745  size_t total_size = 0;
746  for (const FrameStateDescriptor* iter = this; iter != NULL;
747  iter = iter->outer_state_) {
748  total_size += iter->size();
749  }
750  return total_size;
751  }
752 
753  size_t GetHeight(OutputFrameStateCombine override) const {
754  size_t height = size() - parameters_count();
755  switch (override) {
756  case kPushOutput:
757  ++height;
758  break;
759  case kIgnoreOutput:
760  break;
761  }
762  return height;
763  }
764 
765  size_t GetFrameCount() const {
766  size_t count = 0;
767  for (const FrameStateDescriptor* iter = this; iter != NULL;
768  iter = iter->outer_state_) {
769  ++count;
770  }
771  return count;
772  }
773 
774  size_t GetJSFrameCount() const {
775  size_t count = 0;
776  for (const FrameStateDescriptor* iter = this; iter != NULL;
777  iter = iter->outer_state_) {
778  if (iter->type_ == JS_FRAME) {
779  ++count;
780  }
781  }
782  return count;
783  }
784 
785  bool HasContext() const { return type_ == JS_FRAME; }
786 
787  private:
793  size_t stack_count_;
796 };
797 
798 OStream& operator<<(OStream& os, const Constant& constant);
799 
801 typedef std::map<int, Constant, std::less<int>,
803 
807 
808 // Represents architecture-specific generated code before, during, and after
809 // register allocation.
810 // TODO(titzer): s/IsDouble/IsFloat64/
812  public:
813  InstructionSequence(Linkage* linkage, Graph* graph, Schedule* schedule)
814  : graph_(graph),
815  linkage_(linkage),
816  schedule_(schedule),
817  constants_(ConstantMap::key_compare(),
818  ConstantMap::allocator_type(zone())),
819  immediates_(zone()),
820  instructions_(zone()),
821  next_virtual_register_(graph->NodeCount()),
822  pointer_maps_(zone()),
823  doubles_(std::less<int>(), VirtualRegisterSet::allocator_type(zone())),
824  references_(std::less<int>(),
825  VirtualRegisterSet::allocator_type(zone())),
826  deoptimization_entries_(zone()) {}
827 
828  int NextVirtualRegister() { return next_virtual_register_++; }
829  int VirtualRegisterCount() const { return next_virtual_register_; }
830 
831  int ValueCount() const { return graph_->NodeCount(); }
832 
833  int BasicBlockCount() const {
834  return static_cast<int>(schedule_->rpo_order()->size());
835  }
836 
837  BasicBlock* BlockAt(int rpo_number) const {
838  return (*schedule_->rpo_order())[rpo_number];
839  }
840 
841  BasicBlock* GetContainingLoop(BasicBlock* block) {
842  return block->loop_header_;
843  }
844 
845  int GetLoopEnd(BasicBlock* block) const { return block->loop_end_; }
846 
847  BasicBlock* GetBasicBlock(int instruction_index);
848 
849  int GetVirtualRegister(Node* node) const { return node->id(); }
850 
851  bool IsReference(int virtual_register) const;
852  bool IsDouble(int virtual_register) const;
853 
854  void MarkAsReference(int virtual_register);
855  void MarkAsDouble(int virtual_register);
856 
858 
859  Label* GetLabel(BasicBlock* block);
860  BlockStartInstruction* GetBlockStart(BasicBlock* block);
861 
862  typedef InstructionDeque::const_iterator const_iterator;
863  const_iterator begin() const { return instructions_.begin(); }
864  const_iterator end() const { return instructions_.end(); }
865 
866  GapInstruction* GapAt(int index) const {
867  return GapInstruction::cast(InstructionAt(index));
868  }
869  bool IsGapAt(int index) const { return InstructionAt(index)->IsGapMoves(); }
870  Instruction* InstructionAt(int index) const {
871  DCHECK(index >= 0);
872  DCHECK(index < static_cast<int>(instructions_.size()));
873  return instructions_[index];
874  }
875 
876  Frame* frame() { return &frame_; }
877  Graph* graph() const { return graph_; }
878  Isolate* isolate() const { return zone()->isolate(); }
879  Linkage* linkage() const { return linkage_; }
880  Schedule* schedule() const { return schedule_; }
881  const PointerMapDeque* pointer_maps() const { return &pointer_maps_; }
882  Zone* zone() const { return graph_->zone(); }
883 
884  // Used by the code generator while adding instructions.
885  int AddInstruction(Instruction* instr, BasicBlock* block);
886  void StartBlock(BasicBlock* block);
887  void EndBlock(BasicBlock* block);
888 
889  void AddConstant(int virtual_register, Constant constant) {
890  DCHECK(constants_.find(virtual_register) == constants_.end());
891  constants_.insert(std::make_pair(virtual_register, constant));
892  }
893  Constant GetConstant(int virtual_register) const {
894  ConstantMap::const_iterator it = constants_.find(virtual_register);
895  DCHECK(it != constants_.end());
896  DCHECK_EQ(virtual_register, it->first);
897  return it->second;
898  }
899 
901  const Immediates& immediates() const { return immediates_; }
902 
903  int AddImmediate(Constant constant) {
904  int index = static_cast<int>(immediates_.size());
905  immediates_.push_back(constant);
906  return index;
907  }
908  Constant GetImmediate(int index) const {
909  DCHECK(index >= 0);
910  DCHECK(index < static_cast<int>(immediates_.size()));
911  return immediates_[index];
912  }
913 
914  class StateId {
915  public:
916  static StateId FromInt(int id) { return StateId(id); }
917  int ToInt() const { return id_; }
918 
919  private:
920  explicit StateId(int id) : id_(id) {}
921  int id_;
922  };
923 
927 
928  private:
929  friend OStream& operator<<(OStream& os, const InstructionSequence& code);
930 
931  typedef std::set<int, std::less<int>, ZoneIntAllocator> VirtualRegisterSet;
932 
933  Graph* graph_;
934  Linkage* linkage_;
945 };
946 
947 OStream& operator<<(OStream& os, const InstructionSequence& code);
948 
949 } // namespace compiler
950 } // namespace internal
951 } // namespace v8
952 
953 #endif // V8_COMPILER_INSTRUCTION_H_
static const U kShift
Definition: utils.h:204
static U update(U previous, T value)
Definition: utils.h:223
static const T kMax
Definition: utils.h:209
Source to read snapshot and builtins files from.
Definition: lithium-arm.h:372
void * New(int size)
Definition: zone.cc:65
static SubKindOperand * Create(int index, Zone *zone)
Definition: instruction.h:318
BasicBlock * BlockAt(int rpo_number) const
Definition: instruction.h:837
int GetLoopEnd(BasicBlock *block) const
Definition: instruction.h:845
static BlockStartInstruction * New(Zone *zone, BasicBlock *block)
Definition: instruction.h:605
const PointerMapDeque * pointer_maps() const
Definition: instruction.h:881
Schedule * schedule() const
Definition: instruction.h:880
void StartBlock(BasicBlock *block)
SourcePosition source_position() const
Definition: instruction.h:631
Constant GetConstant(int virtual_register) const
Definition: instruction.h:893
Handle< HeapObject > ToHeapObject() const
Definition: instruction.h:704
const_iterator end() const
Definition: instruction.h:864
InstructionOperand * source() const
Definition: instruction.h:275
const ZoneList< InstructionOperand * > * GetNormalizedOperands()
Definition: instruction.h:375
InstructionSequence(Linkage *linkage, Graph *graph, Schedule *schedule)
Definition: instruction.h:813
bool Blocks(InstructionOperand *operand) const
Definition: instruction.h:286
Isolate * isolate() const
Definition: instruction.h:878
DeoptimizationVector deoptimization_entries_
Definition: instruction.h:944
InstructionOperand * source_
Definition: instruction.h:309
void RecordPointer(InstructionOperand *op, Zone *zone)
ExternalReference ToExternalReference() const
Definition: instruction.h:699
static SubKindOperand * cast(InstructionOperand *op)
Definition: instruction.h:324
InstructionOperand * destination() const
Definition: instruction.h:278
VirtualRegisterSet doubles_
Definition: instruction.h:941
InstructionDeque instructions_
Definition: instruction.h:938
Constant(ExternalReference ref)
Definition: instruction.h:670
FrameStateDescriptor * GetFrameStateDescriptor(StateId deoptimization_id)
void set_source(InstructionOperand *operand)
Definition: instruction.h:276
void AddConstant(int virtual_register, Constant constant)
Definition: instruction.h:889
void RemovePointer(InstructionOperand *op)
ZoneList< MoveOperands > move_operands_
Definition: instruction.h:363
InstructionOperand * destination_
Definition: instruction.h:310
StateId AddFrameStateDescriptor(FrameStateDescriptor *descriptor)
Instruction * InstructionAt(int index) const
Definition: instruction.h:870
void AddGapMove(int index, InstructionOperand *from, InstructionOperand *to)
void AddMove(InstructionOperand *from, InstructionOperand *to, Zone *zone)
Definition: instruction.h:351
SourcePositionInstruction(SourcePosition source_position)
Definition: instruction.h:644
void set_instruction_position(int pos)
Definition: instruction.h:384
static const SourcePositionInstruction * cast(const Instruction *instr)
Definition: instruction.h:638
BlockStartInstruction * GetBlockStart(BasicBlock *block)
InstructionDeque::const_iterator const_iterator
Definition: instruction.h:862
void MarkAsReference(int virtual_register)
const ZoneList< MoveOperands > * move_operands() const
Definition: instruction.h:358
SourcePosition source_position_
Definition: instruction.h:651
BasicBlock * GetBasicBlock(int instruction_index)
BlockStartInstruction(BasicBlock *block)
Definition: instruction.h:616
bool IsDouble(int virtual_register) const
Linkage * linkage() const
Definition: instruction.h:879
static SourcePositionInstruction * New(Zone *zone, SourcePosition position)
Definition: instruction.h:626
const_iterator begin() const
Definition: instruction.h:863
static SubKindOperand * cache
Definition: instruction.h:333
void set_destination(InstructionOperand *operand)
Definition: instruction.h:279
static SourcePositionInstruction * cast(Instruction *instr)
Definition: instruction.h:633
VirtualRegisterSet references_
Definition: instruction.h:942
int GetVirtualRegister(Node *node) const
Definition: instruction.h:849
ZoneList< InstructionOperand * > pointer_operands_
Definition: instruction.h:396
void MarkAsDouble(int virtual_register)
Constant GetImmediate(int index) const
Definition: instruction.h:908
Constant(Handle< HeapObject > obj)
Definition: instruction.h:672
bool IsReference(int virtual_register) const
ZoneList< InstructionOperand * > untagged_operands_
Definition: instruction.h:397
ZoneList< MoveOperands > * move_operands()
Definition: instruction.h:357
PointerMapDeque pointer_maps_
Definition: instruction.h:940
int AddInstruction(Instruction *instr, BasicBlock *block)
bool IsGapAt(int index) const
Definition: instruction.h:869
int AddImmediate(Constant constant)
Definition: instruction.h:903
static BlockStartInstruction * cast(Instruction *instr)
Definition: instruction.h:610
BasicBlock * block() const
Definition: instruction.h:602
GapInstruction * GapAt(int index) const
Definition: instruction.h:866
const Immediates & immediates() const
Definition: instruction.h:901
void RecordUntagged(InstructionOperand *op, Zone *zone)
MoveOperands(InstructionOperand *source, InstructionOperand *destination)
Definition: instruction.h:272
BasicBlock * GetContainingLoop(BasicBlock *block)
Definition: instruction.h:841
Label * GetLabel(BasicBlock *block)
void EndBlock(BasicBlock *block)
std::set< int, std::less< int >, ZoneIntAllocator > VirtualRegisterSet
Definition: instruction.h:931
FrameStateDescriptor * outer_state() const
Definition: instruction.h:736
OutputFrameStateCombine state_combine() const
Definition: instruction.h:732
OutputFrameStateCombine frame_state_combine_
Definition: instruction.h:790
size_t GetHeight(OutputFrameStateCombine override) const
Definition: instruction.h:753
FrameStateDescriptor(const FrameStateCallInfo &state_info, size_t parameters_count, size_t locals_count, size_t stack_count, FrameStateDescriptor *outer_state=NULL)
Definition: instruction.h:717
MaybeHandle< JSFunction > jsfunction() const
Definition: instruction.h:737
ParallelMove * GetOrCreateParallelMove(InnerPosition pos, Zone *zone)
Definition: instruction.h:557
static GapInstruction * cast(Instruction *instr)
Definition: instruction.h:573
GapInstruction(InstructionCode opcode)
Definition: instruction.h:584
friend OStream & operator<<(OStream &os, const Instruction &instr)
Definition: instruction.cc:253
static GapInstruction * New(Zone *zone)
Definition: instruction.h:568
ParallelMove * GetParallelMove(InnerPosition pos)
Definition: instruction.h:564
ParallelMove * parallel_moves_[LAST_INNER_POSITION+1]
Definition: instruction.h:593
static const GapInstruction * cast(const Instruction *instr)
Definition: instruction.h:578
bool Equals(InstructionOperand *other) const
Definition: instruction.h:71
InstructionOperand(Kind kind, int index)
Definition: instruction.h:61
void ConvertTo(Kind kind, int index)
Definition: instruction.h:75
InstructionOperand * Output() const
Definition: instruction.h:413
InstructionOperand * operands_[1]
Definition: instruction.h:538
InstructionCode opcode() const
Definition: instruction.h:427
BitField< size_t, 24, 6 > TempCountField
Definition: instruction.h:531
BitField< size_t, 8, 16 > InputCountField
Definition: instruction.h:530
BitField< bool, 31, 1 > IsControlField
Definition: instruction.h:533
AddressingMode addressing_mode() const
Definition: instruction.h:429
static Instruction * New(Zone *zone, InstructionCode opcode)
Definition: instruction.h:438
Instruction(InstructionCode opcode)
Definition: instruction.h:500
InstructionOperand * TempAt(size_t i) const
Definition: instruction.h:422
FlagsCondition flags_condition() const
Definition: instruction.h:433
Instruction(InstructionCode opcode, size_t output_count, InstructionOperand **outputs, size_t input_count, InstructionOperand **inputs, size_t temp_count, InstructionOperand **temps)
Definition: instruction.h:507
PointerMap * pointer_map() const
Definition: instruction.h:485
BitField< bool, 30, 1 > IsCallField
Definition: instruction.h:532
void set_pointer_map(PointerMap *map)
Definition: instruction.h:487
BitField< size_t, 0, 8 > OutputCountField
Definition: instruction.h:529
static Instruction * New(Zone *zone, InstructionCode opcode, size_t output_count, InstructionOperand **outputs, size_t input_count, InstructionOperand **inputs, size_t temp_count, InstructionOperand **temps)
Definition: instruction.h:442
InstructionOperand * InputAt(size_t i) const
Definition: instruction.h:416
InstructionOperand * OutputAt(size_t i) const
Definition: instruction.h:407
UnallocatedOperand(ExtendedPolicy policy)
Definition: instruction.h:123
static const UnallocatedOperand * cast(const InstructionOperand *op)
Definition: instruction.h:160
UnallocatedOperand(BasicPolicy policy, int index)
Definition: instruction.h:130
UnallocatedOperand(ExtendedPolicy policy, int index)
Definition: instruction.h:138
UnallocatedOperand * CopyUnconstrained(Zone *zone)
Definition: instruction.h:154
static UnallocatedOperand * cast(InstructionOperand *op)
Definition: instruction.h:165
UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime)
Definition: instruction.h:147
#define FINAL
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes to(mksnapshot only)") DEFINE_STRING(raw_context_file
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define INSTRUCTION_OPERAND_PREDICATE(name, type, number)
Definition: instruction.h:65
#define INSTRUCTION_OPERAND_LIST(V)
Definition: instruction.h:39
#define INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS(name, type, number)
Definition: instruction.h:341
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
Dest bit_cast(Source const &source)
Definition: macros.h:233
void USE(T)
Definition: macros.h:322
int int32_t
Definition: unicode.cc:24
std::map< int, Constant, std::less< int >, zone_allocator< std::pair< int, Constant > > > ConstantMap
Definition: instruction.h:802
std::ostream & operator<<(std::ostream &os, const MachineType &type)
const InstructionCode kBlockStartInstruction
Definition: instruction.h:35
ZoneVector< FrameStateDescriptor * > DeoptimizationVector
Definition: instruction.h:806
const InstructionCode kGapInstruction
Definition: instruction.h:34
const InstructionCode kSourcePositionInstruction
Definition: instruction.h:36
ZoneDeque< PointerMap * > PointerMapDeque
Definition: instruction.h:805
ZoneVector< InstructionOperand * > InstructionOperandVector
Definition: instruction.h:92
ZoneDeque< Constant > ConstantDeque
Definition: instruction.h:800
ZoneDeque< Instruction * > InstructionDeque
Definition: instruction.h:804
const int kPointerSize
Definition: globals.h:129
static void RoundUp(Vector< char > buffer, int *length, int *decimal_point)
Definition: fixed-dtoa.cc:171
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20