V8 Project
instruction-selector-ia32.cc
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 
8 
9 namespace v8 {
10 namespace internal {
11 namespace compiler {
12 
13 // Adds IA32-specific methods for generating operands.
14 class IA32OperandGenerator FINAL : public OperandGenerator {
15  public:
16  explicit IA32OperandGenerator(InstructionSelector* selector)
17  : OperandGenerator(selector) {}
18 
20  // TODO(dcarney): relax constraint.
21  return UseFixed(node, edx);
22  }
23 
24  bool CanBeImmediate(Node* node) {
25  switch (node->opcode()) {
26  case IrOpcode::kInt32Constant:
27  case IrOpcode::kNumberConstant:
28  case IrOpcode::kExternalConstant:
29  return true;
30  case IrOpcode::kHeapConstant: {
31  // Constants in new space cannot be used as immediates in V8 because
32  // the GC does not scan code objects when collecting the new generation.
33  Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node);
34  return !isolate()->heap()->InNewSpace(*value.handle());
35  }
36  default:
37  return false;
38  }
39  }
40 
41  bool CanBeBetterLeftOperand(Node* node) const {
42  return !selector()->IsLive(node);
43  }
44 };
45 
46 
48  public:
49  AddressingModeMatcher(IA32OperandGenerator* g, Node* base, Node* index)
53  mode_(kMode_None) {
54  Int32Matcher index_imm(index);
55  if (index_imm.HasValue()) {
56  int32_t displacement = index_imm.Value();
57  // Compute base operand and fold base immediate into displacement.
58  Int32Matcher base_imm(base);
59  if (!base_imm.HasValue()) {
60  base_operand_ = g->UseRegister(base);
61  } else {
62  displacement += base_imm.Value();
63  }
64  if (displacement != 0 || base_operand_ == NULL) {
65  displacement_operand_ = g->TempImmediate(displacement);
66  }
67  if (base_operand_ == NULL) {
68  mode_ = kMode_MI;
69  } else {
70  if (displacement == 0) {
71  mode_ = kMode_MR;
72  } else {
73  mode_ = kMode_MRI;
74  }
75  }
76  } else {
77  // Compute index and displacement.
78  IndexAndDisplacementMatcher matcher(index);
79  index_operand_ = g->UseRegister(matcher.index_node());
80  int32_t displacement = matcher.displacement();
81  // Compute base operand and fold base immediate into displacement.
82  Int32Matcher base_imm(base);
83  if (!base_imm.HasValue()) {
84  base_operand_ = g->UseRegister(base);
85  } else {
86  displacement += base_imm.Value();
87  }
88  // Compute displacement operand.
89  if (displacement != 0) {
90  displacement_operand_ = g->TempImmediate(displacement);
91  }
92  // Compute mode with scale factor one.
93  if (base_operand_ == NULL) {
94  if (displacement_operand_ == NULL) {
95  mode_ = kMode_M1;
96  } else {
97  mode_ = kMode_M1I;
98  }
99  } else {
100  if (displacement_operand_ == NULL) {
101  mode_ = kMode_MR1;
102  } else {
103  mode_ = kMode_MR1I;
104  }
105  }
106  // Adjust mode to actual scale factor.
107  mode_ = GetMode(mode_, matcher.power());
108  // Don't emit instructions with scale factor 1 if there's no base.
109  if (mode_ == kMode_M1) {
110  mode_ = kMode_MR;
111  } else if (mode_ == kMode_M1I) {
112  mode_ = kMode_MRI;
113  }
114  }
115  DCHECK_NE(kMode_None, mode_);
116  }
117 
119  return static_cast<AddressingMode>(static_cast<int>(one) + power);
120  }
121 
122  size_t SetInputs(InstructionOperand** inputs) {
123  size_t input_count = 0;
124  // Compute inputs_ and input_count.
125  if (base_operand_ != NULL) {
126  inputs[input_count++] = base_operand_;
127  }
128  if (index_operand_ != NULL) {
129  inputs[input_count++] = index_operand_;
130  }
131  if (displacement_operand_ != NULL) {
132  inputs[input_count++] = displacement_operand_;
133  }
134  DCHECK_NE(input_count, 0);
135  return input_count;
136  }
137 
138  static const int kMaxInputCount = 3;
143 };
144 
145 
146 void InstructionSelector::VisitLoad(Node* node) {
147  MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node));
148  MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node));
149  Node* base = node->InputAt(0);
150  Node* index = node->InputAt(1);
151 
152  ArchOpcode opcode;
153  // TODO(titzer): signed/unsigned small loads
154  switch (rep) {
155  case kRepFloat32:
156  opcode = kIA32Movss;
157  break;
158  case kRepFloat64:
159  opcode = kIA32Movsd;
160  break;
161  case kRepBit: // Fall through.
162  case kRepWord8:
163  opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl;
164  break;
165  case kRepWord16:
166  opcode = typ == kTypeInt32 ? kIA32Movsxwl : kIA32Movzxwl;
167  break;
168  case kRepTagged: // Fall through.
169  case kRepWord32:
170  opcode = kIA32Movl;
171  break;
172  default:
173  UNREACHABLE();
174  return;
175  }
176 
177  IA32OperandGenerator g(this);
178  AddressingModeMatcher matcher(&g, base, index);
179  InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_);
180  InstructionOperand* outputs[] = {g.DefineAsRegister(node)};
181  InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount];
182  size_t input_count = matcher.SetInputs(inputs);
183  Emit(code, 1, outputs, input_count, inputs);
184 }
185 
186 
187 void InstructionSelector::VisitStore(Node* node) {
188  IA32OperandGenerator g(this);
189  Node* base = node->InputAt(0);
190  Node* index = node->InputAt(1);
191  Node* value = node->InputAt(2);
192 
193  StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node);
194  MachineType rep = RepresentationOf(store_rep.machine_type());
195  if (store_rep.write_barrier_kind() == kFullWriteBarrier) {
196  DCHECK_EQ(kRepTagged, rep);
197  // TODO(dcarney): refactor RecordWrite function to take temp registers
198  // and pass them here instead of using fixed regs
199  // TODO(dcarney): handle immediate indices.
200  InstructionOperand* temps[] = {g.TempRegister(ecx), g.TempRegister(edx)};
201  Emit(kIA32StoreWriteBarrier, NULL, g.UseFixed(base, ebx),
202  g.UseFixed(index, ecx), g.UseFixed(value, edx), arraysize(temps),
203  temps);
204  return;
205  }
206  DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
207 
208  ArchOpcode opcode;
209  switch (rep) {
210  case kRepFloat32:
211  opcode = kIA32Movss;
212  break;
213  case kRepFloat64:
214  opcode = kIA32Movsd;
215  break;
216  case kRepBit: // Fall through.
217  case kRepWord8:
218  opcode = kIA32Movb;
219  break;
220  case kRepWord16:
221  opcode = kIA32Movw;
222  break;
223  case kRepTagged: // Fall through.
224  case kRepWord32:
225  opcode = kIA32Movl;
226  break;
227  default:
228  UNREACHABLE();
229  return;
230  }
231 
232  InstructionOperand* val;
233  if (g.CanBeImmediate(value)) {
234  val = g.UseImmediate(value);
235  } else if (rep == kRepWord8 || rep == kRepBit) {
236  val = g.UseByteRegister(value);
237  } else {
238  val = g.UseRegister(value);
239  }
240 
241  AddressingModeMatcher matcher(&g, base, index);
242  InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_);
243  InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount + 1];
244  size_t input_count = matcher.SetInputs(inputs);
245  inputs[input_count++] = val;
246  Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs);
247 }
248 
249 
250 // Shared routine for multiple binary operations.
251 static void VisitBinop(InstructionSelector* selector, Node* node,
252  InstructionCode opcode, FlagsContinuation* cont) {
253  IA32OperandGenerator g(selector);
254  Int32BinopMatcher m(node);
255  Node* left = m.left().node();
256  Node* right = m.right().node();
257  InstructionOperand* inputs[4];
258  size_t input_count = 0;
259  InstructionOperand* outputs[2];
260  size_t output_count = 0;
261 
262  // TODO(turbofan): match complex addressing modes.
263  if (g.CanBeImmediate(right)) {
264  inputs[input_count++] = g.Use(left);
265  inputs[input_count++] = g.UseImmediate(right);
266  } else {
267  if (node->op()->HasProperty(Operator::kCommutative) &&
268  g.CanBeBetterLeftOperand(right)) {
269  std::swap(left, right);
270  }
271  inputs[input_count++] = g.UseRegister(left);
272  inputs[input_count++] = g.Use(right);
273  }
274 
275  if (cont->IsBranch()) {
276  inputs[input_count++] = g.Label(cont->true_block());
277  inputs[input_count++] = g.Label(cont->false_block());
278  }
279 
280  outputs[output_count++] = g.DefineSameAsFirst(node);
281  if (cont->IsSet()) {
282  // TODO(turbofan): Use byte register here.
283  outputs[output_count++] = g.DefineAsRegister(cont->result());
284  }
285 
286  DCHECK_NE(0, input_count);
287  DCHECK_NE(0, output_count);
288  DCHECK_GE(arraysize(inputs), input_count);
289  DCHECK_GE(arraysize(outputs), output_count);
290 
291  Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
292  outputs, input_count, inputs);
293  if (cont->IsBranch()) instr->MarkAsControl();
294 }
295 
296 
297 // Shared routine for multiple binary operations.
298 static void VisitBinop(InstructionSelector* selector, Node* node,
299  InstructionCode opcode) {
300  FlagsContinuation cont;
301  VisitBinop(selector, node, opcode, &cont);
302 }
303 
304 
305 void InstructionSelector::VisitWord32And(Node* node) {
306  VisitBinop(this, node, kIA32And);
307 }
308 
309 
310 void InstructionSelector::VisitWord32Or(Node* node) {
311  VisitBinop(this, node, kIA32Or);
312 }
313 
314 
315 void InstructionSelector::VisitWord32Xor(Node* node) {
316  IA32OperandGenerator g(this);
317  Int32BinopMatcher m(node);
318  if (m.right().Is(-1)) {
319  Emit(kIA32Not, g.DefineSameAsFirst(node), g.Use(m.left().node()));
320  } else {
321  VisitBinop(this, node, kIA32Xor);
322  }
323 }
324 
325 
326 // Shared routine for multiple shift operations.
327 static inline void VisitShift(InstructionSelector* selector, Node* node,
328  ArchOpcode opcode) {
329  IA32OperandGenerator g(selector);
330  Node* left = node->InputAt(0);
331  Node* right = node->InputAt(1);
332 
333  // TODO(turbofan): assembler only supports some addressing modes for shifts.
334  if (g.CanBeImmediate(right)) {
335  selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
336  g.UseImmediate(right));
337  } else {
338  Int32BinopMatcher m(node);
339  if (m.right().IsWord32And()) {
340  Int32BinopMatcher mright(right);
341  if (mright.right().Is(0x1F)) {
342  right = mright.left().node();
343  }
344  }
345  selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
346  g.UseFixed(right, ecx));
347  }
348 }
349 
350 
351 void InstructionSelector::VisitWord32Shl(Node* node) {
352  VisitShift(this, node, kIA32Shl);
353 }
354 
355 
356 void InstructionSelector::VisitWord32Shr(Node* node) {
357  VisitShift(this, node, kIA32Shr);
358 }
359 
360 
361 void InstructionSelector::VisitWord32Sar(Node* node) {
362  VisitShift(this, node, kIA32Sar);
363 }
364 
365 
366 void InstructionSelector::VisitWord32Ror(Node* node) {
367  VisitShift(this, node, kIA32Ror);
368 }
369 
370 
371 void InstructionSelector::VisitInt32Add(Node* node) {
372  VisitBinop(this, node, kIA32Add);
373 }
374 
375 
376 void InstructionSelector::VisitInt32Sub(Node* node) {
377  IA32OperandGenerator g(this);
378  Int32BinopMatcher m(node);
379  if (m.left().Is(0)) {
380  Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node()));
381  } else {
382  VisitBinop(this, node, kIA32Sub);
383  }
384 }
385 
386 
387 void InstructionSelector::VisitInt32Mul(Node* node) {
388  IA32OperandGenerator g(this);
389  Int32BinopMatcher m(node);
390  Node* left = m.left().node();
391  Node* right = m.right().node();
392  if (g.CanBeImmediate(right)) {
393  Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left),
394  g.UseImmediate(right));
395  } else {
396  if (g.CanBeBetterLeftOperand(right)) {
397  std::swap(left, right);
398  }
399  Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left),
400  g.Use(right));
401  }
402 }
403 
404 
405 static inline void VisitDiv(InstructionSelector* selector, Node* node,
406  ArchOpcode opcode) {
407  IA32OperandGenerator g(selector);
408  InstructionOperand* temps[] = {g.TempRegister(edx)};
409  size_t temp_count = arraysize(temps);
410  selector->Emit(opcode, g.DefineAsFixed(node, eax),
411  g.UseFixed(node->InputAt(0), eax),
412  g.UseUnique(node->InputAt(1)), temp_count, temps);
413 }
414 
415 
416 void InstructionSelector::VisitInt32Div(Node* node) {
417  VisitDiv(this, node, kIA32Idiv);
418 }
419 
420 
421 void InstructionSelector::VisitInt32UDiv(Node* node) {
422  VisitDiv(this, node, kIA32Udiv);
423 }
424 
425 
426 static inline void VisitMod(InstructionSelector* selector, Node* node,
427  ArchOpcode opcode) {
428  IA32OperandGenerator g(selector);
429  InstructionOperand* temps[] = {g.TempRegister(eax), g.TempRegister(edx)};
430  size_t temp_count = arraysize(temps);
431  selector->Emit(opcode, g.DefineAsFixed(node, edx),
432  g.UseFixed(node->InputAt(0), eax),
433  g.UseUnique(node->InputAt(1)), temp_count, temps);
434 }
435 
436 
437 void InstructionSelector::VisitInt32Mod(Node* node) {
438  VisitMod(this, node, kIA32Idiv);
439 }
440 
441 
442 void InstructionSelector::VisitInt32UMod(Node* node) {
443  VisitMod(this, node, kIA32Udiv);
444 }
445 
446 
447 void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) {
448  IA32OperandGenerator g(this);
449  // TODO(turbofan): IA32 SSE conversions should take an operand.
450  Emit(kSSECvtss2sd, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)));
451 }
452 
453 
454 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
455  IA32OperandGenerator g(this);
456  Emit(kSSEInt32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
457 }
458 
459 
460 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
461  IA32OperandGenerator g(this);
462  // TODO(turbofan): IA32 SSE LoadUint32() should take an operand.
463  Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node),
464  g.UseRegister(node->InputAt(0)));
465 }
466 
467 
468 void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
469  IA32OperandGenerator g(this);
470  Emit(kSSEFloat64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
471 }
472 
473 
474 void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
475  IA32OperandGenerator g(this);
476  Emit(kSSEFloat64ToUint32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
477 }
478 
479 
480 void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
481  IA32OperandGenerator g(this);
482  // TODO(turbofan): IA32 SSE conversions should take an operand.
483  Emit(kSSECvtsd2ss, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)));
484 }
485 
486 
487 void InstructionSelector::VisitFloat64Add(Node* node) {
488  IA32OperandGenerator g(this);
489  Emit(kSSEFloat64Add, g.DefineSameAsFirst(node),
490  g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
491 }
492 
493 
494 void InstructionSelector::VisitFloat64Sub(Node* node) {
495  IA32OperandGenerator g(this);
496  Emit(kSSEFloat64Sub, g.DefineSameAsFirst(node),
497  g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
498 }
499 
500 
501 void InstructionSelector::VisitFloat64Mul(Node* node) {
502  IA32OperandGenerator g(this);
503  Emit(kSSEFloat64Mul, g.DefineSameAsFirst(node),
504  g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
505 }
506 
507 
508 void InstructionSelector::VisitFloat64Div(Node* node) {
509  IA32OperandGenerator g(this);
510  Emit(kSSEFloat64Div, g.DefineSameAsFirst(node),
511  g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
512 }
513 
514 
515 void InstructionSelector::VisitFloat64Mod(Node* node) {
516  IA32OperandGenerator g(this);
517  InstructionOperand* temps[] = {g.TempRegister(eax)};
518  Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node),
519  g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1,
520  temps);
521 }
522 
523 
524 void InstructionSelector::VisitFloat64Sqrt(Node* node) {
525  IA32OperandGenerator g(this);
526  Emit(kSSEFloat64Sqrt, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
527 }
528 
529 
530 void InstructionSelector::VisitInt32AddWithOverflow(Node* node,
531  FlagsContinuation* cont) {
532  VisitBinop(this, node, kIA32Add, cont);
533 }
534 
535 
536 void InstructionSelector::VisitInt32SubWithOverflow(Node* node,
537  FlagsContinuation* cont) {
538  VisitBinop(this, node, kIA32Sub, cont);
539 }
540 
541 
542 // Shared routine for multiple compare operations.
543 static inline void VisitCompare(InstructionSelector* selector,
544  InstructionCode opcode,
545  InstructionOperand* left,
546  InstructionOperand* right,
547  FlagsContinuation* cont) {
548  IA32OperandGenerator g(selector);
549  if (cont->IsBranch()) {
550  selector->Emit(cont->Encode(opcode), NULL, left, right,
551  g.Label(cont->true_block()),
552  g.Label(cont->false_block()))->MarkAsControl();
553  } else {
554  DCHECK(cont->IsSet());
555  // TODO(titzer): Needs byte register.
556  selector->Emit(cont->Encode(opcode), g.DefineAsRegister(cont->result()),
557  left, right);
558  }
559 }
560 
561 
562 // Shared routine for multiple word compare operations.
563 static inline void VisitWordCompare(InstructionSelector* selector, Node* node,
564  InstructionCode opcode,
565  FlagsContinuation* cont, bool commutative) {
566  IA32OperandGenerator g(selector);
567  Node* left = node->InputAt(0);
568  Node* right = node->InputAt(1);
569 
570  // Match immediates on left or right side of comparison.
571  if (g.CanBeImmediate(right)) {
572  VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont);
573  } else if (g.CanBeImmediate(left)) {
574  if (!commutative) cont->Commute();
575  VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont);
576  } else {
577  VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont);
578  }
579 }
580 
581 
582 void InstructionSelector::VisitWord32Test(Node* node, FlagsContinuation* cont) {
583  switch (node->opcode()) {
584  case IrOpcode::kInt32Sub:
585  return VisitWordCompare(this, node, kIA32Cmp, cont, false);
586  case IrOpcode::kWord32And:
587  return VisitWordCompare(this, node, kIA32Test, cont, true);
588  default:
589  break;
590  }
591 
592  IA32OperandGenerator g(this);
593  VisitCompare(this, kIA32Test, g.Use(node), g.TempImmediate(-1), cont);
594 }
595 
596 
597 void InstructionSelector::VisitWord32Compare(Node* node,
598  FlagsContinuation* cont) {
599  VisitWordCompare(this, node, kIA32Cmp, cont, false);
600 }
601 
602 
603 void InstructionSelector::VisitFloat64Compare(Node* node,
604  FlagsContinuation* cont) {
605  IA32OperandGenerator g(this);
606  Node* left = node->InputAt(0);
607  Node* right = node->InputAt(1);
608  VisitCompare(this, kSSEFloat64Cmp, g.UseRegister(left), g.Use(right), cont);
609 }
610 
611 
612 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation,
613  BasicBlock* deoptimization) {
614  IA32OperandGenerator g(this);
615  CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call);
616 
617  FrameStateDescriptor* frame_state_descriptor = NULL;
618 
619  if (descriptor->NeedsFrameState()) {
620  frame_state_descriptor =
621  GetFrameStateDescriptor(call->InputAt(descriptor->InputCount()));
622  }
623 
624  CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
625 
626  // Compute InstructionOperands for inputs and outputs.
627  InitializeCallBuffer(call, &buffer, true, true);
628 
629  // Push any stack arguments.
630  for (NodeVectorRIter input = buffer.pushed_nodes.rbegin();
631  input != buffer.pushed_nodes.rend(); input++) {
632  // TODO(titzer): handle pushing double parameters.
633  Emit(kIA32Push, NULL,
634  g.CanBeImmediate(*input) ? g.UseImmediate(*input) : g.Use(*input));
635  }
636 
637  // Select the appropriate opcode based on the call type.
638  InstructionCode opcode;
639  switch (descriptor->kind()) {
640  case CallDescriptor::kCallCodeObject: {
641  opcode = kArchCallCodeObject;
642  break;
643  }
644  case CallDescriptor::kCallJSFunction:
645  opcode = kArchCallJSFunction;
646  break;
647  default:
648  UNREACHABLE();
649  return;
650  }
651  opcode |= MiscField::encode(descriptor->flags());
652 
653  // Emit the call instruction.
654  Instruction* call_instr =
655  Emit(opcode, buffer.outputs.size(), &buffer.outputs.front(),
656  buffer.instruction_args.size(), &buffer.instruction_args.front());
657 
658  call_instr->MarkAsCall();
659  if (deoptimization != NULL) {
660  DCHECK(continuation != NULL);
661  call_instr->MarkAsControl();
662  }
663 }
664 
665 } // namespace compiler
666 } // namespace internal
667 } // namespace v8
Handle< T > handle() const
Definition: unique.h:99
AddressingMode GetMode(AddressingMode one, int power)
AddressingModeMatcher(IA32OperandGenerator *g, Node *base, Node *index)
bool CanBeBetterLeftOperand(Node *node) const
InstructionOperand * UseByteRegister(Node *node)
IA32OperandGenerator(InstructionSelector *selector)
#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 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 UNREACHABLE()
Definition: logging.h:30
#define DCHECK_NE(v1, v2)
Definition: logging.h:207
#define DCHECK_GE(v1, v2)
Definition: logging.h:208
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
#define arraysize(array)
Definition: macros.h:86
int int32_t
Definition: unicode.cc:24
static void VisitBinop(InstructionSelector *selector, Node *node, InstructionCode opcode, InstructionCode reverse_opcode, FlagsContinuation *cont)
static void VisitDiv(InstructionSelector *selector, Node *node, ArchOpcode div_opcode, ArchOpcode f64i32_opcode, ArchOpcode i32f64_opcode)
BinopMatcher< Int32Matcher, Int32Matcher > Int32BinopMatcher
MachineType TypeOf(MachineType machine_type)
Definition: machine-type.h:70
static void VisitWordCompare(InstructionSelector *selector, Node *node, InstructionCode opcode, FlagsContinuation *cont, bool commutative)
MachineType RepresentationOf(MachineType machine_type)
Definition: machine-type.h:76
static void VisitMod(InstructionSelector *selector, Node *node, ArchOpcode div_opcode, ArchOpcode f64i32_opcode, ArchOpcode i32f64_opcode)
static void VisitShift(InstructionSelector *selector, Node *node, TryMatchShift try_match_shift, FlagsContinuation *cont)
NodeVector::reverse_iterator NodeVectorRIter
Definition: node.h:75
IntMatcher< int32_t, IrOpcode::kInt32Constant > Int32Matcher
Definition: node-matchers.h:79
static void VisitCompare(InstructionSelector *selector, InstructionCode opcode, InstructionOperand *left, InstructionOperand *right, FlagsContinuation *cont)
const Register edx
const Register eax
const Register ebx
const Register ecx
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20