~yolanda.robla/ubuntu/trusty/nodejs/add_distribution

« back to all changes in this revision

Viewing changes to deps/v8/src/arm/lithium-arm.cc

  • Committer: Package Import Robot
  • Author(s): Jérémy Lal
  • Date: 2013-08-14 00:16:46 UTC
  • mfrom: (7.1.40 sid)
  • Revision ID: package-import@ubuntu.com-20130814001646-bzlysfh8sd6mukbo
Tags: 0.10.15~dfsg1-4
* Update 2005 patch, adding a handful of tests that can fail on
  slow platforms.
* Add 1004 patch to fix test failures when writing NaN to buffer
  on mipsel.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright 2011 the V8 project authors. All rights reserved.
 
1
// Copyright 2012 the V8 project authors. All rights reserved.
2
2
// Redistribution and use in source and binary forms, with or without
3
3
// modification, are permitted provided that the following conditions are
4
4
// met:
108
108
}
109
109
 
110
110
 
111
 
template<int R, int I, int T>
112
 
void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) {
 
111
void LInstruction::PrintDataTo(StringStream* stream) {
113
112
  stream->Add("= ");
114
 
  for (int i = 0; i < inputs_.length(); i++) {
 
113
  for (int i = 0; i < InputCount(); i++) {
115
114
    if (i > 0) stream->Add(" ");
116
 
    inputs_[i]->PrintTo(stream);
 
115
    InputAt(i)->PrintTo(stream);
117
116
  }
118
117
}
119
118
 
120
119
 
121
 
template<int R, int I, int T>
122
 
void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) {
123
 
  for (int i = 0; i < results_.length(); i++) {
124
 
    if (i > 0) stream->Add(" ");
125
 
    results_[i]->PrintTo(stream);
126
 
  }
 
120
void LInstruction::PrintOutputOperandTo(StringStream* stream) {
 
121
  if (HasResult()) result()->PrintTo(stream);
127
122
}
128
123
 
129
124
 
199
194
 
200
195
void LBranch::PrintDataTo(StringStream* stream) {
201
196
  stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
202
 
  InputAt(0)->PrintTo(stream);
 
197
  value()->PrintTo(stream);
203
198
}
204
199
 
205
200
 
206
201
void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
207
202
  stream->Add("if ");
208
 
  InputAt(0)->PrintTo(stream);
 
203
  left()->PrintTo(stream);
209
204
  stream->Add(" %s ", Token::String(op()));
210
 
  InputAt(1)->PrintTo(stream);
 
205
  right()->PrintTo(stream);
211
206
  stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
212
207
}
213
208
 
214
209
 
215
 
void LIsNullAndBranch::PrintDataTo(StringStream* stream) {
 
210
void LIsNilAndBranch::PrintDataTo(StringStream* stream) {
216
211
  stream->Add("if ");
217
 
  InputAt(0)->PrintTo(stream);
218
 
  stream->Add(is_strict() ? " === null" : " == null");
 
212
  value()->PrintTo(stream);
 
213
  stream->Add(kind() == kStrictEquality ? " === " : " == ");
 
214
  stream->Add(nil() == kNullValue ? "null" : "undefined");
219
215
  stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
220
216
}
221
217
 
222
218
 
223
219
void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
224
220
  stream->Add("if is_object(");
225
 
  InputAt(0)->PrintTo(stream);
 
221
  value()->PrintTo(stream);
 
222
  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
 
223
}
 
224
 
 
225
 
 
226
void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
 
227
  stream->Add("if is_string(");
 
228
  value()->PrintTo(stream);
226
229
  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
227
230
}
228
231
 
229
232
 
230
233
void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
231
234
  stream->Add("if is_smi(");
232
 
  InputAt(0)->PrintTo(stream);
 
235
  value()->PrintTo(stream);
233
236
  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
234
237
}
235
238
 
236
239
 
237
240
void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
238
241
  stream->Add("if is_undetectable(");
239
 
  InputAt(0)->PrintTo(stream);
 
242
  value()->PrintTo(stream);
 
243
  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
 
244
}
 
245
 
 
246
 
 
247
void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
 
248
  stream->Add("if string_compare(");
 
249
  left()->PrintTo(stream);
 
250
  right()->PrintTo(stream);
240
251
  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
241
252
}
242
253
 
243
254
 
244
255
void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
245
256
  stream->Add("if has_instance_type(");
246
 
  InputAt(0)->PrintTo(stream);
 
257
  value()->PrintTo(stream);
247
258
  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
248
259
}
249
260
 
250
261
 
251
262
void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
252
263
  stream->Add("if has_cached_array_index(");
253
 
  InputAt(0)->PrintTo(stream);
 
264
  value()->PrintTo(stream);
254
265
  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
255
266
}
256
267
 
257
268
 
258
269
void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
259
270
  stream->Add("if class_of_test(");
260
 
  InputAt(0)->PrintTo(stream);
 
271
  value()->PrintTo(stream);
261
272
  stream->Add(", \"%o\") then B%d else B%d",
262
273
              *hydrogen()->class_name(),
263
274
              true_block_id(),
267
278
 
268
279
void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
269
280
  stream->Add("if typeof ");
270
 
  InputAt(0)->PrintTo(stream);
 
281
  value()->PrintTo(stream);
271
282
  stream->Add(" == \"%s\" then B%d else B%d",
272
283
              *hydrogen()->type_literal()->ToCString(),
273
284
              true_block_id(), false_block_id());
281
292
 
282
293
void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
283
294
  stream->Add("/%s ", hydrogen()->OpName());
284
 
  InputAt(0)->PrintTo(stream);
 
295
  value()->PrintTo(stream);
285
296
}
286
297
 
287
298
 
288
299
void LLoadContextSlot::PrintDataTo(StringStream* stream) {
289
 
  InputAt(0)->PrintTo(stream);
 
300
  context()->PrintTo(stream);
290
301
  stream->Add("[%d]", slot_index());
291
302
}
292
303
 
293
304
 
294
305
void LStoreContextSlot::PrintDataTo(StringStream* stream) {
295
 
  InputAt(0)->PrintTo(stream);
 
306
  context()->PrintTo(stream);
296
307
  stream->Add("[%d] <- ", slot_index());
297
 
  InputAt(1)->PrintTo(stream);
 
308
  value()->PrintTo(stream);
298
309
}
299
310
 
300
311
 
301
312
void LInvokeFunction::PrintDataTo(StringStream* stream) {
302
313
  stream->Add("= ");
303
 
  InputAt(0)->PrintTo(stream);
 
314
  function()->PrintTo(stream);
304
315
  stream->Add(" #%d / ", arity());
305
316
}
306
317
 
329
340
 
330
341
void LCallNew::PrintDataTo(StringStream* stream) {
331
342
  stream->Add("= ");
332
 
  InputAt(0)->PrintTo(stream);
 
343
  constructor()->PrintTo(stream);
333
344
  stream->Add(" #%d / ", arity());
334
345
}
335
346
 
336
347
 
337
348
void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
338
349
  arguments()->PrintTo(stream);
339
 
 
340
350
  stream->Add(" length ");
341
351
  length()->PrintTo(stream);
342
 
 
343
352
  stream->Add(" index ");
344
353
  index()->PrintTo(stream);
345
354
}
390
399
}
391
400
 
392
401
 
393
 
LChunk::LChunk(CompilationInfo* info, HGraph* graph)
394
 
    : spill_slot_count_(0),
395
 
      info_(info),
396
 
      graph_(graph),
397
 
      instructions_(32),
398
 
      pointer_maps_(8),
399
 
      inlined_closures_(1) {
 
402
void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
 
403
  object()->PrintTo(stream);
 
404
  stream->Add(" %p -> %p", *original_map(), *transitioned_map());
400
405
}
401
406
 
402
407
 
403
 
int LChunk::GetNextSpillIndex(bool is_double) {
 
408
int LPlatformChunk::GetNextSpillIndex(bool is_double) {
404
409
  // Skip a slot if for a double-width slot.
405
410
  if (is_double) spill_slot_count_++;
406
411
  return spill_slot_count_++;
407
412
}
408
413
 
409
414
 
410
 
LOperand* LChunk::GetNextSpillSlot(bool is_double)  {
 
415
LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double)  {
411
416
  int index = GetNextSpillIndex(is_double);
412
417
  if (is_double) {
413
 
    return LDoubleStackSlot::Create(index);
414
 
  } else {
415
 
    return LStackSlot::Create(index);
416
 
  }
417
 
}
418
 
 
419
 
 
420
 
void LChunk::MarkEmptyBlocks() {
421
 
  HPhase phase("Mark empty blocks", this);
422
 
  for (int i = 0; i < graph()->blocks()->length(); ++i) {
423
 
    HBasicBlock* block = graph()->blocks()->at(i);
424
 
    int first = block->first_instruction_index();
425
 
    int last = block->last_instruction_index();
426
 
    LInstruction* first_instr = instructions()->at(first);
427
 
    LInstruction* last_instr = instructions()->at(last);
428
 
 
429
 
    LLabel* label = LLabel::cast(first_instr);
430
 
    if (last_instr->IsGoto()) {
431
 
      LGoto* goto_instr = LGoto::cast(last_instr);
432
 
      if (label->IsRedundant() &&
433
 
          !label->is_loop_header()) {
434
 
        bool can_eliminate = true;
435
 
        for (int i = first + 1; i < last && can_eliminate; ++i) {
436
 
          LInstruction* cur = instructions()->at(i);
437
 
          if (cur->IsGap()) {
438
 
            LGap* gap = LGap::cast(cur);
439
 
            if (!gap->IsRedundant()) {
440
 
              can_eliminate = false;
441
 
            }
442
 
          } else {
443
 
            can_eliminate = false;
444
 
          }
445
 
        }
446
 
 
447
 
        if (can_eliminate) {
448
 
          label->set_replacement(GetLabel(goto_instr->block_id()));
449
 
        }
450
 
      }
451
 
    }
452
 
  }
453
 
}
454
 
 
455
 
 
456
 
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
457
 
  LInstructionGap* gap = new LInstructionGap(block);
458
 
  int index = -1;
459
 
  if (instr->IsControl()) {
460
 
    instructions_.Add(gap);
461
 
    index = instructions_.length();
462
 
    instructions_.Add(instr);
463
 
  } else {
464
 
    index = instructions_.length();
465
 
    instructions_.Add(instr);
466
 
    instructions_.Add(gap);
467
 
  }
468
 
  if (instr->HasPointerMap()) {
469
 
    pointer_maps_.Add(instr->pointer_map());
470
 
    instr->pointer_map()->set_lithium_position(index);
471
 
  }
472
 
}
473
 
 
474
 
 
475
 
LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
476
 
  return LConstantOperand::Create(constant->id());
477
 
}
478
 
 
479
 
 
480
 
int LChunk::GetParameterStackSlot(int index) const {
481
 
  // The receiver is at index 0, the first parameter at index 1, so we
482
 
  // shift all parameter indexes down by the number of parameters, and
483
 
  // make sure they end up negative so they are distinguishable from
484
 
  // spill slots.
485
 
  int result = index - info()->scope()->num_parameters() - 1;
486
 
  ASSERT(result < 0);
487
 
  return result;
488
 
}
489
 
 
490
 
// A parameter relative to ebp in the arguments stub.
491
 
int LChunk::ParameterAt(int index) {
492
 
  ASSERT(-1 <= index);  // -1 is the receiver.
493
 
  return (1 + info()->scope()->num_parameters() - index) *
494
 
      kPointerSize;
495
 
}
496
 
 
497
 
 
498
 
LGap* LChunk::GetGapAt(int index) const {
499
 
  return LGap::cast(instructions_[index]);
500
 
}
501
 
 
502
 
 
503
 
bool LChunk::IsGapAt(int index) const {
504
 
  return instructions_[index]->IsGap();
505
 
}
506
 
 
507
 
 
508
 
int LChunk::NearestGapPos(int index) const {
509
 
  while (!IsGapAt(index)) index--;
510
 
  return index;
511
 
}
512
 
 
513
 
 
514
 
void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
515
 
  GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to);
516
 
}
517
 
 
518
 
 
519
 
Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
520
 
  return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
521
 
}
522
 
 
523
 
 
524
 
Representation LChunk::LookupLiteralRepresentation(
525
 
    LConstantOperand* operand) const {
526
 
  return graph_->LookupValue(operand->index())->representation();
527
 
}
528
 
 
529
 
 
530
 
LChunk* LChunkBuilder::Build() {
 
418
    return LDoubleStackSlot::Create(index, zone());
 
419
  } else {
 
420
    return LStackSlot::Create(index, zone());
 
421
  }
 
422
}
 
423
 
 
424
 
 
425
LPlatformChunk* LChunkBuilder::Build() {
531
426
  ASSERT(is_unused());
532
 
  chunk_ = new LChunk(info(), graph());
533
 
  HPhase phase("Building chunk", chunk_);
 
427
  chunk_ = new(zone()) LPlatformChunk(info(), graph());
 
428
  HPhase phase("L_Building chunk", chunk_);
534
429
  status_ = BUILDING;
535
430
  const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
536
431
  for (int i = 0; i < blocks->length(); i++) {
544
439
}
545
440
 
546
441
 
547
 
void LChunkBuilder::Abort(const char* format, ...) {
548
 
  if (FLAG_trace_bailout) {
549
 
    SmartArrayPointer<char> name(
550
 
        info()->shared_info()->DebugName()->ToCString());
551
 
    PrintF("Aborting LChunk building in @\"%s\": ", *name);
552
 
    va_list arguments;
553
 
    va_start(arguments, format);
554
 
    OS::VPrint(format, arguments);
555
 
    va_end(arguments);
556
 
    PrintF("\n");
557
 
  }
 
442
void LChunkBuilder::Abort(const char* reason) {
 
443
  info()->set_bailout_reason(reason);
558
444
  status_ = ABORTED;
559
445
}
560
446
 
561
447
 
562
 
LRegister* LChunkBuilder::ToOperand(Register reg) {
563
 
  return LRegister::Create(Register::ToAllocationIndex(reg));
564
 
}
565
 
 
566
 
 
567
448
LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
568
 
  return new LUnallocated(LUnallocated::FIXED_REGISTER,
569
 
                          Register::ToAllocationIndex(reg));
 
449
  return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
 
450
                                  Register::ToAllocationIndex(reg));
570
451
}
571
452
 
572
453
 
573
454
LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
574
 
  return new LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
575
 
                          DoubleRegister::ToAllocationIndex(reg));
 
455
  return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
 
456
                                  DoubleRegister::ToAllocationIndex(reg));
576
457
}
577
458
 
578
459
 
587
468
 
588
469
 
589
470
LOperand* LChunkBuilder::UseRegister(HValue* value) {
590
 
  return Use(value, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
 
471
  return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
591
472
}
592
473
 
593
474
 
594
475
LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
595
476
  return Use(value,
596
 
             new LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
597
 
                              LUnallocated::USED_AT_START));
 
477
             new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
 
478
                                      LUnallocated::USED_AT_START));
598
479
}
599
480
 
600
481
 
601
482
LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
602
 
  return Use(value, new LUnallocated(LUnallocated::WRITABLE_REGISTER));
 
483
  return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
603
484
}
604
485
 
605
486
 
606
487
LOperand* LChunkBuilder::Use(HValue* value) {
607
 
  return Use(value, new LUnallocated(LUnallocated::NONE));
 
488
  return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
608
489
}
609
490
 
610
491
 
611
492
LOperand* LChunkBuilder::UseAtStart(HValue* value) {
612
 
  return Use(value, new LUnallocated(LUnallocated::NONE,
613
 
                                     LUnallocated::USED_AT_START));
 
493
  return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
 
494
                                             LUnallocated::USED_AT_START));
614
495
}
615
496
 
616
497
 
645
526
LOperand* LChunkBuilder::UseAny(HValue* value) {
646
527
  return value->IsConstant()
647
528
      ? chunk_->DefineConstantOperand(HConstant::cast(value))
648
 
      :  Use(value, new LUnallocated(LUnallocated::ANY));
 
529
      :  Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
649
530
}
650
531
 
651
532
 
654
535
    HInstruction* instr = HInstruction::cast(value);
655
536
    VisitInstruction(instr);
656
537
  }
657
 
  allocator_->RecordUse(value, operand);
 
538
  operand->set_virtual_register(value->id());
658
539
  return operand;
659
540
}
660
541
 
662
543
template<int I, int T>
663
544
LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
664
545
                                    LUnallocated* result) {
665
 
  allocator_->RecordDefinition(current_instruction_, result);
 
546
  result->set_virtual_register(current_instruction_->id());
666
547
  instr->set_result(result);
667
548
  return instr;
668
549
}
669
550
 
670
551
 
671
552
template<int I, int T>
672
 
LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr) {
673
 
  return Define(instr, new LUnallocated(LUnallocated::NONE));
674
 
}
675
 
 
676
 
 
677
 
template<int I, int T>
678
553
LInstruction* LChunkBuilder::DefineAsRegister(
679
554
    LTemplateInstruction<1, I, T>* instr) {
680
 
  return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
 
555
  return Define(instr,
 
556
                new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
681
557
}
682
558
 
683
559
 
684
560
template<int I, int T>
685
561
LInstruction* LChunkBuilder::DefineAsSpilled(
686
562
    LTemplateInstruction<1, I, T>* instr, int index) {
687
 
  return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index));
 
563
  return Define(instr,
 
564
                new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
688
565
}
689
566
 
690
567
 
691
568
template<int I, int T>
692
569
LInstruction* LChunkBuilder::DefineSameAsFirst(
693
570
    LTemplateInstruction<1, I, T>* instr) {
694
 
  return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
 
571
  return Define(instr,
 
572
                new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
695
573
}
696
574
 
697
575
 
711
589
 
712
590
LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
713
591
  HEnvironment* hydrogen_env = current_block_->last_environment();
714
 
  instr->set_environment(CreateEnvironment(hydrogen_env));
715
 
  return instr;
716
 
}
717
 
 
718
 
 
719
 
LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
720
 
    LInstruction* instr, int ast_id) {
721
 
  ASSERT(instruction_pending_deoptimization_environment_ == NULL);
722
 
  ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
723
 
  instruction_pending_deoptimization_environment_ = instr;
724
 
  pending_deoptimization_ast_id_ = ast_id;
725
 
  return instr;
726
 
}
727
 
 
728
 
 
729
 
void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
730
 
  instruction_pending_deoptimization_environment_ = NULL;
731
 
  pending_deoptimization_ast_id_ = AstNode::kNoNumber;
 
592
  int argument_index_accumulator = 0;
 
593
  instr->set_environment(CreateEnvironment(hydrogen_env,
 
594
                                           &argument_index_accumulator));
 
595
  return instr;
732
596
}
733
597
 
734
598
 
741
605
  instr->MarkAsCall();
742
606
  instr = AssignPointerMap(instr);
743
607
 
744
 
  if (hinstr->HasSideEffects()) {
 
608
  if (hinstr->HasObservableSideEffects()) {
745
609
    ASSERT(hinstr->next()->IsSimulate());
746
610
    HSimulate* sim = HSimulate::cast(hinstr->next());
747
 
    instr = SetInstructionPendingDeoptimizationEnvironment(
748
 
        instr, sim->ast_id());
 
611
    ASSERT(instruction_pending_deoptimization_environment_ == NULL);
 
612
    ASSERT(pending_deoptimization_ast_id_.IsNone());
 
613
    instruction_pending_deoptimization_environment_ = instr;
 
614
    pending_deoptimization_ast_id_ = sim->ast_id();
749
615
  }
750
616
 
751
617
  // If instruction does not have side-effects lazy deoptimization
753
619
  // Thus we still need to attach environment to this call even if
754
620
  // call sequence can not deoptimize eagerly.
755
621
  bool needs_environment =
756
 
      (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects();
 
622
      (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
 
623
      !hinstr->HasObservableSideEffects();
757
624
  if (needs_environment && !instr->HasEnvironment()) {
758
625
    instr = AssignEnvironment(instr);
759
626
  }
762
629
}
763
630
 
764
631
 
765
 
LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
766
 
  instr->MarkAsSaveDoubles();
767
 
  return instr;
768
 
}
769
 
 
770
 
 
771
632
LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
772
633
  ASSERT(!instr->HasPointerMap());
773
 
  instr->set_pointer_map(new LPointerMap(position_));
 
634
  instr->set_pointer_map(new(zone()) LPointerMap(position_, zone()));
774
635
  return instr;
775
636
}
776
637
 
777
638
 
778
639
LUnallocated* LChunkBuilder::TempRegister() {
779
 
  LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
780
 
  allocator_->RecordTemporary(operand);
 
640
  LUnallocated* operand =
 
641
      new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
 
642
  operand->set_virtual_register(allocator_->GetVirtualRegister());
 
643
  if (!allocator_->AllocationOk()) Abort("Not enough virtual registers.");
781
644
  return operand;
782
645
}
783
646
 
784
647
 
785
648
LOperand* LChunkBuilder::FixedTemp(Register reg) {
786
649
  LUnallocated* operand = ToUnallocated(reg);
787
 
  allocator_->RecordTemporary(operand);
 
650
  ASSERT(operand->HasFixedPolicy());
788
651
  return operand;
789
652
}
790
653
 
791
654
 
792
655
LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) {
793
656
  LUnallocated* operand = ToUnallocated(reg);
794
 
  allocator_->RecordTemporary(operand);
 
657
  ASSERT(operand->HasFixedPolicy());
795
658
  return operand;
796
659
}
797
660
 
798
661
 
799
662
LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
800
 
  return new LLabel(instr->block());
 
663
  return new(zone()) LLabel(instr->block());
801
664
}
802
665
 
803
666
 
804
667
LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
805
 
  return AssignEnvironment(new LDeoptimize);
 
668
  return AssignEnvironment(new(zone()) LDeoptimize);
806
669
}
807
670
 
808
671
 
809
672
LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
810
 
  return AssignEnvironment(new LDeoptimize);
811
 
}
812
 
 
813
 
 
814
 
LInstruction* LChunkBuilder::DoBit(Token::Value op,
815
 
                                   HBitwiseBinaryOperation* instr) {
816
 
  if (instr->representation().IsInteger32()) {
817
 
    ASSERT(instr->left()->representation().IsInteger32());
818
 
    ASSERT(instr->right()->representation().IsInteger32());
819
 
 
820
 
    LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
821
 
    LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
822
 
    return DefineAsRegister(new LBitI(op, left, right));
823
 
  } else {
824
 
    ASSERT(instr->representation().IsTagged());
825
 
    ASSERT(instr->left()->representation().IsTagged());
826
 
    ASSERT(instr->right()->representation().IsTagged());
827
 
 
828
 
    LOperand* left = UseFixed(instr->left(), r1);
829
 
    LOperand* right = UseFixed(instr->right(), r0);
830
 
    LArithmeticT* result = new LArithmeticT(op, left, right);
831
 
    return MarkAsCall(DefineFixed(result, r0), instr);
832
 
  }
 
673
  return AssignEnvironment(new(zone()) LDeoptimize);
833
674
}
834
675
 
835
676
 
841
682
 
842
683
    LOperand* left = UseFixed(instr->left(), r1);
843
684
    LOperand* right = UseFixed(instr->right(), r0);
844
 
    LArithmeticT* result = new LArithmeticT(op, left, right);
 
685
    LArithmeticT* result = new(zone()) LArithmeticT(op, left, right);
845
686
    return MarkAsCall(DefineFixed(result, r0), instr);
846
687
  }
847
688
 
863
704
 
864
705
  // Shift operations can only deoptimize if we do a logical shift
865
706
  // by 0 and the result cannot be truncated to int32.
866
 
  bool may_deopt = (op == Token::SHR && constant_value == 0);
867
707
  bool does_deopt = false;
868
 
  if (may_deopt) {
869
 
    for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
870
 
      if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
871
 
        does_deopt = true;
872
 
        break;
 
708
  if (op == Token::SHR && constant_value == 0) {
 
709
    if (FLAG_opt_safe_uint32_operations) {
 
710
      does_deopt = !instr->CheckFlag(HInstruction::kUint32);
 
711
    } else {
 
712
      for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
 
713
        if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
 
714
          does_deopt = true;
 
715
          break;
 
716
        }
873
717
      }
874
718
    }
875
719
  }
876
720
 
877
721
  LInstruction* result =
878
 
      DefineAsRegister(new LShiftI(op, left, right, does_deopt));
 
722
      DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
879
723
  return does_deopt ? AssignEnvironment(result) : result;
880
724
}
881
725
 
888
732
  ASSERT(op != Token::MOD);
889
733
  LOperand* left = UseRegisterAtStart(instr->left());
890
734
  LOperand* right = UseRegisterAtStart(instr->right());
891
 
  LArithmeticD* result = new LArithmeticD(op, left, right);
 
735
  LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
892
736
  return DefineAsRegister(result);
893
737
}
894
738
 
906
750
  ASSERT(right->representation().IsTagged());
907
751
  LOperand* left_operand = UseFixed(left, r1);
908
752
  LOperand* right_operand = UseFixed(right, r0);
909
 
  LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
 
753
  LArithmeticT* result =
 
754
      new(zone()) LArithmeticT(op, left_operand, right_operand);
910
755
  return MarkAsCall(DefineFixed(result, r0), instr);
911
756
}
912
757
 
994
839
}
995
840
 
996
841
 
997
 
LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) {
 
842
LEnvironment* LChunkBuilder::CreateEnvironment(
 
843
    HEnvironment* hydrogen_env,
 
844
    int* argument_index_accumulator) {
998
845
  if (hydrogen_env == NULL) return NULL;
999
846
 
1000
 
  LEnvironment* outer = CreateEnvironment(hydrogen_env->outer());
1001
 
  int ast_id = hydrogen_env->ast_id();
1002
 
  ASSERT(ast_id != AstNode::kNoNumber);
 
847
  LEnvironment* outer =
 
848
      CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
 
849
  BailoutId ast_id = hydrogen_env->ast_id();
 
850
  ASSERT(!ast_id.IsNone() ||
 
851
         hydrogen_env->frame_type() != JS_FUNCTION);
1003
852
  int value_count = hydrogen_env->length();
1004
 
  LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
1005
 
                                          ast_id,
1006
 
                                          hydrogen_env->parameter_count(),
1007
 
                                          argument_count_,
1008
 
                                          value_count,
1009
 
                                          outer);
1010
 
  int argument_index = 0;
 
853
  LEnvironment* result = new(zone()) LEnvironment(
 
854
      hydrogen_env->closure(),
 
855
      hydrogen_env->frame_type(),
 
856
      ast_id,
 
857
      hydrogen_env->parameter_count(),
 
858
      argument_count_,
 
859
      value_count,
 
860
      outer,
 
861
      hydrogen_env->entry(),
 
862
      zone());
 
863
  int argument_index = *argument_index_accumulator;
1011
864
  for (int i = 0; i < value_count; ++i) {
1012
865
    if (hydrogen_env->is_special_index(i)) continue;
1013
866
 
1016
869
    if (value->IsArgumentsObject()) {
1017
870
      op = NULL;
1018
871
    } else if (value->IsPushArgument()) {
1019
 
      op = new LArgument(argument_index++);
 
872
      op = new(zone()) LArgument(argument_index++);
1020
873
    } else {
1021
874
      op = UseAny(value);
1022
875
    }
1023
 
    result->AddValue(op, value->representation());
 
876
    result->AddValue(op,
 
877
                     value->representation(),
 
878
                     value->CheckFlag(HInstruction::kUint32));
 
879
  }
 
880
 
 
881
  if (hydrogen_env->frame_type() == JS_FUNCTION) {
 
882
    *argument_index_accumulator = argument_index;
1024
883
  }
1025
884
 
1026
885
  return result;
1028
887
 
1029
888
 
1030
889
LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
1031
 
  return new LGoto(instr->FirstSuccessor()->block_id());
 
890
  return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
1032
891
}
1033
892
 
1034
893
 
1035
894
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
1036
 
  HValue* v = instr->value();
1037
 
  if (v->EmitAtUses()) {
1038
 
    HBasicBlock* successor = HConstant::cast(v)->ToBoolean()
 
895
  HValue* value = instr->value();
 
896
  if (value->EmitAtUses()) {
 
897
    HBasicBlock* successor = HConstant::cast(value)->ToBoolean()
1039
898
        ? instr->FirstSuccessor()
1040
899
        : instr->SecondSuccessor();
1041
 
    return new LGoto(successor->block_id());
1042
 
  }
1043
 
  return AssignEnvironment(new LBranch(UseRegister(v)));
 
900
    return new(zone()) LGoto(successor->block_id());
 
901
  }
 
902
 
 
903
  LBranch* result = new(zone()) LBranch(UseRegister(value));
 
904
  // Tagged values that are not known smis or booleans require a
 
905
  // deoptimization environment.
 
906
  Representation rep = value->representation();
 
907
  HType type = value->type();
 
908
  if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean()) {
 
909
    return AssignEnvironment(result);
 
910
  }
 
911
  return result;
1044
912
}
1045
913
 
1046
914
 
1049
917
  ASSERT(instr->value()->representation().IsTagged());
1050
918
  LOperand* value = UseRegisterAtStart(instr->value());
1051
919
  LOperand* temp = TempRegister();
1052
 
  return new LCmpMapAndBranch(value, temp);
 
920
  return new(zone()) LCmpMapAndBranch(value, temp);
1053
921
}
1054
922
 
1055
923
 
1056
 
LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
1057
 
  return DefineAsRegister(new LArgumentsLength(UseRegister(length->value())));
 
924
LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) {
 
925
  LOperand* value = UseRegister(instr->value());
 
926
  return DefineAsRegister(new(zone()) LArgumentsLength(value));
1058
927
}
1059
928
 
1060
929
 
1061
930
LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1062
 
  return DefineAsRegister(new LArgumentsElements);
 
931
  return DefineAsRegister(new(zone()) LArgumentsElements);
1063
932
}
1064
933
 
1065
934
 
1066
935
LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
1067
936
  LInstanceOf* result =
1068
 
      new LInstanceOf(UseFixed(instr->left(), r0),
 
937
      new(zone()) LInstanceOf(UseFixed(instr->left(), r0),
1069
938
                      UseFixed(instr->right(), r1));
1070
939
  return MarkAsCall(DefineFixed(result, r0), instr);
1071
940
}
1074
943
LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1075
944
    HInstanceOfKnownGlobal* instr) {
1076
945
  LInstanceOfKnownGlobal* result =
1077
 
      new LInstanceOfKnownGlobal(UseFixed(instr->left(), r0), FixedTemp(r4));
 
946
      new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), r0),
 
947
                                         FixedTemp(r4));
1078
948
  return MarkAsCall(DefineFixed(result, r0), instr);
1079
949
}
1080
950
 
1081
951
 
 
952
LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
 
953
  LOperand* receiver = UseRegisterAtStart(instr->receiver());
 
954
  LOperand* function = UseRegisterAtStart(instr->function());
 
955
  LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function);
 
956
  return AssignEnvironment(DefineSameAsFirst(result));
 
957
}
 
958
 
 
959
 
1082
960
LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1083
961
  LOperand* function = UseFixed(instr->function(), r1);
1084
962
  LOperand* receiver = UseFixed(instr->receiver(), r0);
1085
963
  LOperand* length = UseFixed(instr->length(), r2);
1086
964
  LOperand* elements = UseFixed(instr->elements(), r3);
1087
 
  LApplyArguments* result = new LApplyArguments(function,
 
965
  LApplyArguments* result = new(zone()) LApplyArguments(function,
1088
966
                                                receiver,
1089
967
                                                length,
1090
968
                                                elements);
1095
973
LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1096
974
  ++argument_count_;
1097
975
  LOperand* argument = Use(instr->argument());
1098
 
  return new LPushArgument(argument);
 
976
  return new(zone()) LPushArgument(argument);
1099
977
}
1100
978
 
1101
979
 
1102
980
LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
1103
 
  return instr->HasNoUses() ? NULL : DefineAsRegister(new LThisFunction);
 
981
  return instr->HasNoUses()
 
982
      ? NULL
 
983
      : DefineAsRegister(new(zone()) LThisFunction);
1104
984
}
1105
985
 
1106
986
 
1107
987
LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1108
 
  return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
 
988
  return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
1109
989
}
1110
990
 
1111
991
 
1112
992
LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
1113
993
  LOperand* context = UseRegisterAtStart(instr->value());
1114
 
  return DefineAsRegister(new LOuterContext(context));
 
994
  return DefineAsRegister(new(zone()) LOuterContext(context));
 
995
}
 
996
 
 
997
 
 
998
LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
 
999
  return MarkAsCall(new(zone()) LDeclareGlobals, instr);
1115
1000
}
1116
1001
 
1117
1002
 
1118
1003
LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
1119
1004
  LOperand* context = UseRegisterAtStart(instr->value());
1120
 
  return DefineAsRegister(new LGlobalObject(context));
 
1005
  return DefineAsRegister(new(zone()) LGlobalObject(context));
1121
1006
}
1122
1007
 
1123
1008
 
1124
1009
LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
1125
1010
  LOperand* global_object = UseRegisterAtStart(instr->value());
1126
 
  return DefineAsRegister(new LGlobalReceiver(global_object));
 
1011
  return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
1127
1012
}
1128
1013
 
1129
1014
 
1130
1015
LInstruction* LChunkBuilder::DoCallConstantFunction(
1131
1016
    HCallConstantFunction* instr) {
1132
1017
  argument_count_ -= instr->argument_count();
1133
 
  return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr);
 
1018
  return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, r0), instr);
1134
1019
}
1135
1020
 
1136
1021
 
1137
1022
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1138
1023
  LOperand* function = UseFixed(instr->function(), r1);
1139
1024
  argument_count_ -= instr->argument_count();
1140
 
  LInvokeFunction* result = new LInvokeFunction(function);
 
1025
  LInvokeFunction* result = new(zone()) LInvokeFunction(function);
1141
1026
  return MarkAsCall(DefineFixed(result, r0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1142
1027
}
1143
1028
 
1144
1029
 
1145
1030
LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1146
1031
  BuiltinFunctionId op = instr->op();
1147
 
  if (op == kMathLog || op == kMathSin || op == kMathCos) {
 
1032
  if (op == kMathLog || op == kMathSin || op == kMathCos || op == kMathTan) {
1148
1033
    LOperand* input = UseFixedDouble(instr->value(), d2);
1149
 
    LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL);
 
1034
    LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, NULL);
1150
1035
    return MarkAsCall(DefineFixedDouble(result, d2), instr);
 
1036
  } else if (op == kMathPowHalf) {
 
1037
    LOperand* input = UseFixedDouble(instr->value(), d2);
 
1038
    LOperand* temp = FixedTemp(d3);
 
1039
    LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
 
1040
    return DefineFixedDouble(result, d2);
1151
1041
  } else {
1152
1042
    LOperand* input = UseRegisterAtStart(instr->value());
1153
 
    LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
1154
 
    LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
 
1043
 
 
1044
    LOperand* temp = (op == kMathRound) ? FixedTemp(d3) : NULL;
 
1045
    LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
1155
1046
    switch (op) {
1156
1047
      case kMathAbs:
1157
1048
        return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1161
1052
        return DefineAsRegister(result);
1162
1053
      case kMathRound:
1163
1054
        return AssignEnvironment(DefineAsRegister(result));
1164
 
      case kMathPowHalf:
1165
 
        return DefineAsRegister(result);
1166
1055
      default:
1167
1056
        UNREACHABLE();
1168
1057
        return NULL;
1175
1064
  ASSERT(instr->key()->representation().IsTagged());
1176
1065
  argument_count_ -= instr->argument_count();
1177
1066
  LOperand* key = UseFixed(instr->key(), r2);
1178
 
  return MarkAsCall(DefineFixed(new LCallKeyed(key), r0), instr);
 
1067
  return MarkAsCall(DefineFixed(new(zone()) LCallKeyed(key), r0), instr);
1179
1068
}
1180
1069
 
1181
1070
 
1182
1071
LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1183
1072
  argument_count_ -= instr->argument_count();
1184
 
  return MarkAsCall(DefineFixed(new LCallNamed, r0), instr);
 
1073
  return MarkAsCall(DefineFixed(new(zone()) LCallNamed, r0), instr);
1185
1074
}
1186
1075
 
1187
1076
 
1188
1077
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1189
1078
  argument_count_ -= instr->argument_count();
1190
 
  return MarkAsCall(DefineFixed(new LCallGlobal, r0), instr);
 
1079
  return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, r0), instr);
1191
1080
}
1192
1081
 
1193
1082
 
1194
1083
LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1195
1084
  argument_count_ -= instr->argument_count();
1196
 
  return MarkAsCall(DefineFixed(new LCallKnownGlobal, r0), instr);
 
1085
  return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, r0), instr);
1197
1086
}
1198
1087
 
1199
1088
 
1200
1089
LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1201
1090
  LOperand* constructor = UseFixed(instr->constructor(), r1);
1202
1091
  argument_count_ -= instr->argument_count();
1203
 
  LCallNew* result = new LCallNew(constructor);
 
1092
  LCallNew* result = new(zone()) LCallNew(constructor);
1204
1093
  return MarkAsCall(DefineFixed(result, r0), instr);
1205
1094
}
1206
1095
 
1207
1096
 
1208
1097
LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
 
1098
  LOperand* function = UseFixed(instr->function(), r1);
1209
1099
  argument_count_ -= instr->argument_count();
1210
 
  return MarkAsCall(DefineFixed(new LCallFunction, r0), instr);
 
1100
  return MarkAsCall(DefineFixed(new(zone()) LCallFunction(function), r0),
 
1101
                    instr);
1211
1102
}
1212
1103
 
1213
1104
 
1214
1105
LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1215
1106
  argument_count_ -= instr->argument_count();
1216
 
  return MarkAsCall(DefineFixed(new LCallRuntime, r0), instr);
 
1107
  return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, r0), instr);
1217
1108
}
1218
1109
 
1219
1110
 
1232
1123
}
1233
1124
 
1234
1125
 
1235
 
LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
1236
 
  return DoBit(Token::BIT_AND, instr);
 
1126
LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
 
1127
  if (instr->representation().IsInteger32()) {
 
1128
    ASSERT(instr->left()->representation().IsInteger32());
 
1129
    ASSERT(instr->right()->representation().IsInteger32());
 
1130
 
 
1131
    LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
 
1132
    LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
 
1133
    return DefineAsRegister(new(zone()) LBitI(left, right));
 
1134
  } else {
 
1135
    ASSERT(instr->representation().IsTagged());
 
1136
    ASSERT(instr->left()->representation().IsTagged());
 
1137
    ASSERT(instr->right()->representation().IsTagged());
 
1138
 
 
1139
    LOperand* left = UseFixed(instr->left(), r1);
 
1140
    LOperand* right = UseFixed(instr->right(), r0);
 
1141
    LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right);
 
1142
    return MarkAsCall(DefineFixed(result, r0), instr);
 
1143
  }
1237
1144
}
1238
1145
 
1239
1146
 
1240
1147
LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1241
1148
  ASSERT(instr->value()->representation().IsInteger32());
1242
1149
  ASSERT(instr->representation().IsInteger32());
1243
 
  return DefineAsRegister(new LBitNotI(UseRegisterAtStart(instr->value())));
1244
 
}
1245
 
 
1246
 
 
1247
 
LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
1248
 
  return DoBit(Token::BIT_OR, instr);
1249
 
}
1250
 
 
1251
 
 
1252
 
LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
1253
 
  return DoBit(Token::BIT_XOR, instr);
 
1150
  if (instr->HasNoUses()) return NULL;
 
1151
  LOperand* value = UseRegisterAtStart(instr->value());
 
1152
  return DefineAsRegister(new(zone()) LBitNotI(value));
1254
1153
}
1255
1154
 
1256
1155
 
1266
1165
    LOperand* dividend = UseFixed(instr->left(), r0);
1267
1166
    LOperand* divisor = UseFixed(instr->right(), r1);
1268
1167
    return AssignEnvironment(AssignPointerMap(
1269
 
             DefineFixed(new LDivI(dividend, divisor), r0)));
 
1168
             DefineFixed(new(zone()) LDivI(dividend, divisor), r0)));
1270
1169
  } else {
1271
1170
    return DoArithmeticT(Token::DIV, instr);
1272
1171
  }
1273
1172
}
1274
1173
 
1275
1174
 
 
1175
bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) {
 
1176
  uint32_t divisor_abs = abs(divisor);
 
1177
  // Dividing by 0, 1, and powers of 2 is easy.
 
1178
  // Note that IsPowerOf2(0) returns true;
 
1179
  ASSERT(IsPowerOf2(0) == true);
 
1180
  if (IsPowerOf2(divisor_abs)) return true;
 
1181
 
 
1182
  // We have magic numbers for a few specific divisors.
 
1183
  // Details and proofs can be found in:
 
1184
  // - Hacker's Delight, Henry S. Warren, Jr.
 
1185
  // - The PowerPC Compiler Writer’s Guide
 
1186
  // and probably many others.
 
1187
  //
 
1188
  // We handle
 
1189
  //   <divisor with magic numbers> * <power of 2>
 
1190
  // but not
 
1191
  //   <divisor with magic numbers> * <other divisor with magic numbers>
 
1192
  int32_t power_of_2_factor =
 
1193
    CompilerIntrinsics::CountTrailingZeros(divisor_abs);
 
1194
  DivMagicNumbers magic_numbers =
 
1195
    DivMagicNumberFor(divisor_abs >> power_of_2_factor);
 
1196
  if (magic_numbers.M != InvalidDivMagicNumber.M) return true;
 
1197
 
 
1198
  return false;
 
1199
}
 
1200
 
 
1201
 
 
1202
HValue* LChunkBuilder::SimplifiedDividendForMathFloorOfDiv(HValue* dividend) {
 
1203
  // A value with an integer representation does not need to be transformed.
 
1204
  if (dividend->representation().IsInteger32()) {
 
1205
    return dividend;
 
1206
  // A change from an integer32 can be replaced by the integer32 value.
 
1207
  } else if (dividend->IsChange() &&
 
1208
      HChange::cast(dividend)->from().IsInteger32()) {
 
1209
    return HChange::cast(dividend)->value();
 
1210
  }
 
1211
  return NULL;
 
1212
}
 
1213
 
 
1214
 
 
1215
HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
 
1216
  // Only optimize when we have magic numbers for the divisor.
 
1217
  // The standard integer division routine is usually slower than transitionning
 
1218
  // to VFP.
 
1219
  if (divisor->IsConstant() &&
 
1220
      HConstant::cast(divisor)->HasInteger32Value()) {
 
1221
    HConstant* constant_val = HConstant::cast(divisor);
 
1222
    int32_t int32_val = constant_val->Integer32Value();
 
1223
    if (LChunkBuilder::HasMagicNumberForDivisor(int32_val)) {
 
1224
      return constant_val->CopyToRepresentation(Representation::Integer32(),
 
1225
                                                divisor->block()->zone());
 
1226
    }
 
1227
  }
 
1228
  return NULL;
 
1229
}
 
1230
 
 
1231
 
 
1232
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
 
1233
    HValue* right = instr->right();
 
1234
    LOperand* dividend = UseRegister(instr->left());
 
1235
    LOperand* divisor = UseRegisterOrConstant(right);
 
1236
    LOperand* remainder = TempRegister();
 
1237
    ASSERT(right->IsConstant() &&
 
1238
           HConstant::cast(right)->HasInteger32Value() &&
 
1239
           HasMagicNumberForDivisor(HConstant::cast(right)->Integer32Value()));
 
1240
    return AssignEnvironment(DefineAsRegister(
 
1241
          new(zone()) LMathFloorOfDiv(dividend, divisor, remainder)));
 
1242
}
 
1243
 
 
1244
 
1276
1245
LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1277
1246
  if (instr->representation().IsInteger32()) {
1278
1247
    ASSERT(instr->left()->representation().IsInteger32());
1282
1251
    if (instr->HasPowerOf2Divisor()) {
1283
1252
      ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1284
1253
      LOperand* value = UseRegisterAtStart(instr->left());
1285
 
      mod = new LModI(value, UseOrConstant(instr->right()));
 
1254
      mod = new(zone()) LModI(value, UseOrConstant(instr->right()));
1286
1255
    } else {
1287
1256
      LOperand* dividend = UseRegister(instr->left());
1288
1257
      LOperand* divisor = UseRegister(instr->right());
1289
 
      mod = new LModI(dividend,
1290
 
                      divisor,
1291
 
                      TempRegister(),
1292
 
                      FixedTemp(d10),
1293
 
                      FixedTemp(d11));
 
1258
      mod = new(zone()) LModI(dividend,
 
1259
                              divisor,
 
1260
                              TempRegister(),
 
1261
                              FixedTemp(d10),
 
1262
                              FixedTemp(d11));
1294
1263
    }
1295
1264
 
1296
1265
    if (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1308
1277
    // TODO(fschneider): Allow any register as input registers.
1309
1278
    LOperand* left = UseFixedDouble(instr->left(), d1);
1310
1279
    LOperand* right = UseFixedDouble(instr->right(), d2);
1311
 
    LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
 
1280
    LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right);
1312
1281
    return MarkAsCall(DefineFixedDouble(result, d1), instr);
1313
1282
  }
1314
1283
}
1329
1298
    } else {
1330
1299
      left = UseRegisterAtStart(instr->LeastConstantOperand());
1331
1300
    }
1332
 
    return AssignEnvironment(DefineAsRegister(new LMulI(left, right, temp)));
 
1301
    LMulI* mul = new(zone()) LMulI(left, right, temp);
 
1302
    if (instr->CheckFlag(HValue::kCanOverflow) ||
 
1303
        instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
 
1304
      AssignEnvironment(mul);
 
1305
    }
 
1306
    return DefineAsRegister(mul);
1333
1307
 
1334
1308
  } else if (instr->representation().IsDouble()) {
1335
1309
    return DoArithmeticD(Token::MUL, instr);
1346
1320
    ASSERT(instr->right()->representation().IsInteger32());
1347
1321
    LOperand* left = UseRegisterAtStart(instr->left());
1348
1322
    LOperand* right = UseOrConstantAtStart(instr->right());
1349
 
    LSubI* sub = new LSubI(left, right);
 
1323
    LSubI* sub = new(zone()) LSubI(left, right);
1350
1324
    LInstruction* result = DefineAsRegister(sub);
1351
1325
    if (instr->CheckFlag(HValue::kCanOverflow)) {
1352
1326
      result = AssignEnvironment(result);
1366
1340
    ASSERT(instr->right()->representation().IsInteger32());
1367
1341
    LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1368
1342
    LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1369
 
    LAddI* add = new LAddI(left, right);
 
1343
    LAddI* add = new(zone()) LAddI(left, right);
1370
1344
    LInstruction* result = DefineAsRegister(add);
1371
1345
    if (instr->CheckFlag(HValue::kCanOverflow)) {
1372
1346
      result = AssignEnvironment(result);
1381
1355
}
1382
1356
 
1383
1357
 
 
1358
LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
 
1359
  LOperand* left = NULL;
 
1360
  LOperand* right = NULL;
 
1361
  if (instr->representation().IsInteger32()) {
 
1362
    ASSERT(instr->left()->representation().IsInteger32());
 
1363
    ASSERT(instr->right()->representation().IsInteger32());
 
1364
    left = UseRegisterAtStart(instr->LeastConstantOperand());
 
1365
    right = UseOrConstantAtStart(instr->MostConstantOperand());
 
1366
  } else {
 
1367
    ASSERT(instr->representation().IsDouble());
 
1368
    ASSERT(instr->left()->representation().IsDouble());
 
1369
    ASSERT(instr->right()->representation().IsDouble());
 
1370
    left = UseRegisterAtStart(instr->left());
 
1371
    right = UseRegisterAtStart(instr->right());
 
1372
  }
 
1373
  return DefineAsRegister(new(zone()) LMathMinMax(left, right));
 
1374
}
 
1375
 
 
1376
 
1384
1377
LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1385
1378
  ASSERT(instr->representation().IsDouble());
1386
1379
  // We call a C function for double power. It can't trigger a GC.
1390
1383
  LOperand* left = UseFixedDouble(instr->left(), d1);
1391
1384
  LOperand* right = exponent_type.IsDouble() ?
1392
1385
      UseFixedDouble(instr->right(), d2) :
1393
 
      UseFixed(instr->right(), r0);
1394
 
  LPower* result = new LPower(left, right);
 
1386
      UseFixed(instr->right(), r2);
 
1387
  LPower* result = new(zone()) LPower(left, right);
1395
1388
  return MarkAsCall(DefineFixedDouble(result, d3),
1396
1389
                    instr,
1397
1390
                    CAN_DEOPTIMIZE_EAGERLY);
1398
1391
}
1399
1392
 
1400
1393
 
 
1394
LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
 
1395
  ASSERT(instr->representation().IsDouble());
 
1396
  ASSERT(instr->global_object()->representation().IsTagged());
 
1397
  LOperand* global_object = UseFixed(instr->global_object(), r0);
 
1398
  LRandom* result = new(zone()) LRandom(global_object);
 
1399
  return MarkAsCall(DefineFixedDouble(result, d7), instr);
 
1400
}
 
1401
 
 
1402
 
1401
1403
LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1402
 
  Token::Value op = instr->token();
1403
1404
  ASSERT(instr->left()->representation().IsTagged());
1404
1405
  ASSERT(instr->right()->representation().IsTagged());
1405
 
  bool reversed = (op == Token::GT || op == Token::LTE);
1406
 
  LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1);
1407
 
  LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0);
1408
 
  LCmpT* result = new LCmpT(left, right);
 
1406
  LOperand* left = UseFixed(instr->left(), r1);
 
1407
  LOperand* right = UseFixed(instr->right(), r0);
 
1408
  LCmpT* result = new(zone()) LCmpT(left, right);
1409
1409
  return MarkAsCall(DefineFixed(result, r0), instr);
1410
1410
}
1411
1411
 
1416
1416
  if (r.IsInteger32()) {
1417
1417
    ASSERT(instr->left()->representation().IsInteger32());
1418
1418
    ASSERT(instr->right()->representation().IsInteger32());
1419
 
    LOperand* left = UseRegisterAtStart(instr->left());
1420
 
    LOperand* right = UseRegisterAtStart(instr->right());
1421
 
    return new LCmpIDAndBranch(left, right);
 
1419
    LOperand* left = UseRegisterOrConstantAtStart(instr->left());
 
1420
    LOperand* right = UseRegisterOrConstantAtStart(instr->right());
 
1421
    return new(zone()) LCmpIDAndBranch(left, right);
1422
1422
  } else {
1423
1423
    ASSERT(r.IsDouble());
1424
1424
    ASSERT(instr->left()->representation().IsDouble());
1425
1425
    ASSERT(instr->right()->representation().IsDouble());
1426
1426
    LOperand* left = UseRegisterAtStart(instr->left());
1427
1427
    LOperand* right = UseRegisterAtStart(instr->right());
1428
 
    return new LCmpIDAndBranch(left, right);
 
1428
    return new(zone()) LCmpIDAndBranch(left, right);
1429
1429
  }
1430
1430
}
1431
1431
 
1434
1434
    HCompareObjectEqAndBranch* instr) {
1435
1435
  LOperand* left = UseRegisterAtStart(instr->left());
1436
1436
  LOperand* right = UseRegisterAtStart(instr->right());
1437
 
  return new LCmpObjectEqAndBranch(left, right);
 
1437
  return new(zone()) LCmpObjectEqAndBranch(left, right);
1438
1438
}
1439
1439
 
1440
1440
 
1441
1441
LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
1442
1442
    HCompareConstantEqAndBranch* instr) {
1443
 
  return new LCmpConstantEqAndBranch(UseRegisterAtStart(instr->value()));
 
1443
  LOperand* value = UseRegisterAtStart(instr->value());
 
1444
  return new(zone()) LCmpConstantEqAndBranch(value);
1444
1445
}
1445
1446
 
1446
1447
 
1447
 
LInstruction* LChunkBuilder::DoIsNullAndBranch(HIsNullAndBranch* instr) {
 
1448
LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) {
1448
1449
  ASSERT(instr->value()->representation().IsTagged());
1449
 
  return new LIsNullAndBranch(UseRegisterAtStart(instr->value()));
 
1450
  return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value()));
1450
1451
}
1451
1452
 
1452
1453
 
1453
1454
LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1454
1455
  ASSERT(instr->value()->representation().IsTagged());
1455
 
  LOperand* temp = TempRegister();
1456
 
  return new LIsObjectAndBranch(UseRegisterAtStart(instr->value()), temp);
 
1456
  LOperand* value = UseRegisterAtStart(instr->value());
 
1457
  LOperand* temp = TempRegister();
 
1458
  return new(zone()) LIsObjectAndBranch(value, temp);
 
1459
}
 
1460
 
 
1461
 
 
1462
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
 
1463
  ASSERT(instr->value()->representation().IsTagged());
 
1464
  LOperand* value = UseRegisterAtStart(instr->value());
 
1465
  LOperand* temp = TempRegister();
 
1466
  return new(zone()) LIsStringAndBranch(value, temp);
1457
1467
}
1458
1468
 
1459
1469
 
1460
1470
LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1461
1471
  ASSERT(instr->value()->representation().IsTagged());
1462
 
  return new LIsSmiAndBranch(Use(instr->value()));
 
1472
  return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1463
1473
}
1464
1474
 
1465
1475
 
1466
1476
LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1467
1477
    HIsUndetectableAndBranch* instr) {
1468
1478
  ASSERT(instr->value()->representation().IsTagged());
1469
 
  return new LIsUndetectableAndBranch(UseRegisterAtStart(instr->value()),
1470
 
                                      TempRegister());
 
1479
  LOperand* value = UseRegisterAtStart(instr->value());
 
1480
  return new(zone()) LIsUndetectableAndBranch(value, TempRegister());
 
1481
}
 
1482
 
 
1483
 
 
1484
LInstruction* LChunkBuilder::DoStringCompareAndBranch(
 
1485
    HStringCompareAndBranch* instr) {
 
1486
  ASSERT(instr->left()->representation().IsTagged());
 
1487
  ASSERT(instr->right()->representation().IsTagged());
 
1488
  LOperand* left = UseFixed(instr->left(), r1);
 
1489
  LOperand* right = UseFixed(instr->right(), r0);
 
1490
  LStringCompareAndBranch* result =
 
1491
      new(zone()) LStringCompareAndBranch(left, right);
 
1492
  return MarkAsCall(result, instr);
1471
1493
}
1472
1494
 
1473
1495
 
1474
1496
LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1475
1497
    HHasInstanceTypeAndBranch* instr) {
1476
1498
  ASSERT(instr->value()->representation().IsTagged());
1477
 
  return new LHasInstanceTypeAndBranch(UseRegisterAtStart(instr->value()));
 
1499
  LOperand* value = UseRegisterAtStart(instr->value());
 
1500
  return new(zone()) LHasInstanceTypeAndBranch(value);
1478
1501
}
1479
1502
 
1480
1503
 
1483
1506
  ASSERT(instr->value()->representation().IsTagged());
1484
1507
  LOperand* value = UseRegisterAtStart(instr->value());
1485
1508
 
1486
 
  return DefineAsRegister(new LGetCachedArrayIndex(value));
 
1509
  return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
1487
1510
}
1488
1511
 
1489
1512
 
1490
1513
LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1491
1514
    HHasCachedArrayIndexAndBranch* instr) {
1492
1515
  ASSERT(instr->value()->representation().IsTagged());
1493
 
  return new LHasCachedArrayIndexAndBranch(
 
1516
  return new(zone()) LHasCachedArrayIndexAndBranch(
1494
1517
      UseRegisterAtStart(instr->value()));
1495
1518
}
1496
1519
 
1498
1521
LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1499
1522
    HClassOfTestAndBranch* instr) {
1500
1523
  ASSERT(instr->value()->representation().IsTagged());
1501
 
  return new LClassOfTestAndBranch(UseTempRegister(instr->value()),
1502
 
                                   TempRegister());
 
1524
  LOperand* value = UseRegister(instr->value());
 
1525
  return new(zone()) LClassOfTestAndBranch(value, TempRegister());
1503
1526
}
1504
1527
 
1505
1528
 
1506
1529
LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1507
1530
  LOperand* array = UseRegisterAtStart(instr->value());
1508
 
  return DefineAsRegister(new LJSArrayLength(array));
 
1531
  return DefineAsRegister(new(zone()) LJSArrayLength(array));
1509
1532
}
1510
1533
 
1511
1534
 
1512
1535
LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
1513
1536
    HFixedArrayBaseLength* instr) {
1514
1537
  LOperand* array = UseRegisterAtStart(instr->value());
1515
 
  return DefineAsRegister(new LFixedArrayBaseLength(array));
 
1538
  return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array));
 
1539
}
 
1540
 
 
1541
 
 
1542
LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
 
1543
  LOperand* map = UseRegisterAtStart(instr->value());
 
1544
  return DefineAsRegister(new(zone()) LMapEnumLength(map));
1516
1545
}
1517
1546
 
1518
1547
 
1519
1548
LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1520
1549
  LOperand* object = UseRegisterAtStart(instr->value());
1521
 
  return DefineAsRegister(new LElementsKind(object));
 
1550
  return DefineAsRegister(new(zone()) LElementsKind(object));
1522
1551
}
1523
1552
 
1524
1553
 
1525
1554
LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1526
1555
  LOperand* object = UseRegister(instr->value());
1527
 
  LValueOf* result = new LValueOf(object, TempRegister());
1528
 
  return AssignEnvironment(DefineAsRegister(result));
 
1556
  LValueOf* result = new(zone()) LValueOf(object, TempRegister());
 
1557
  return DefineAsRegister(result);
 
1558
}
 
1559
 
 
1560
 
 
1561
LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
 
1562
  LOperand* object = UseFixed(instr->value(), r0);
 
1563
  LDateField* result =
 
1564
      new(zone()) LDateField(object, FixedTemp(r1), instr->index());
 
1565
  return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
1529
1566
}
1530
1567
 
1531
1568
 
1532
1569
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1533
 
  return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
1534
 
                                            UseRegister(instr->length())));
 
1570
  LOperand* value = UseRegisterOrConstantAtStart(instr->index());
 
1571
  LOperand* length = UseRegister(instr->length());
 
1572
  return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
1535
1573
}
1536
1574
 
1537
1575
 
1544
1582
 
1545
1583
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1546
1584
  LOperand* value = UseFixed(instr->value(), r0);
1547
 
  return MarkAsCall(new LThrow(value), instr);
 
1585
  return MarkAsCall(new(zone()) LThrow(value), instr);
1548
1586
}
1549
1587
 
1550
1588
 
1567
1605
  if (from.IsTagged()) {
1568
1606
    if (to.IsDouble()) {
1569
1607
      LOperand* value = UseRegister(instr->value());
1570
 
      LNumberUntagD* res = new LNumberUntagD(value);
 
1608
      LNumberUntagD* res = new(zone()) LNumberUntagD(value);
1571
1609
      return AssignEnvironment(DefineAsRegister(res));
1572
1610
    } else {
1573
1611
      ASSERT(to.IsInteger32());
1574
 
      LOperand* value = UseRegister(instr->value());
1575
 
      bool needs_check = !instr->value()->type().IsSmi();
 
1612
      LOperand* value = UseRegisterAtStart(instr->value());
1576
1613
      LInstruction* res = NULL;
1577
 
      if (!needs_check) {
1578
 
        res = DefineSameAsFirst(new LSmiUntag(value, needs_check));
 
1614
      if (instr->value()->type().IsSmi()) {
 
1615
        res = DefineAsRegister(new(zone()) LSmiUntag(value, false));
1579
1616
      } else {
1580
1617
        LOperand* temp1 = TempRegister();
1581
1618
        LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
1582
1619
                                                      : NULL;
1583
 
        LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d11)
1584
 
                                                      : NULL;
1585
 
        res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3));
 
1620
        LOperand* temp3 = FixedTemp(d11);
 
1621
        res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
 
1622
                                                       temp1,
 
1623
                                                       temp2,
 
1624
                                                       temp3));
1586
1625
        res = AssignEnvironment(res);
1587
1626
      }
1588
1627
      return res;
1596
1635
      // Make sure that the temp and result_temp registers are
1597
1636
      // different.
1598
1637
      LUnallocated* result_temp = TempRegister();
1599
 
      LNumberTagD* result = new LNumberTagD(value, temp1, temp2);
 
1638
      LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2);
1600
1639
      Define(result, result_temp);
1601
1640
      return AssignPointerMap(result);
1602
1641
    } else {
1603
1642
      ASSERT(to.IsInteger32());
1604
1643
      LOperand* value = UseRegister(instr->value());
1605
 
      LDoubleToI* res =
1606
 
        new LDoubleToI(value,
1607
 
                       TempRegister(),
1608
 
                       instr->CanTruncateToInt32() ? TempRegister() : NULL);
 
1644
      LOperand* temp1 = TempRegister();
 
1645
      LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL;
 
1646
      LDoubleToI* res = new(zone()) LDoubleToI(value, temp1, temp2);
1609
1647
      return AssignEnvironment(DefineAsRegister(res));
1610
1648
    }
1611
1649
  } else if (from.IsInteger32()) {
1612
1650
    if (to.IsTagged()) {
1613
1651
      HValue* val = instr->value();
1614
 
      LOperand* value = UseRegister(val);
1615
 
      if (val->HasRange() && val->range()->IsInSmiRange()) {
1616
 
        return DefineSameAsFirst(new LSmiTag(value));
1617
 
      } else {
1618
 
        LNumberTagI* result = new LNumberTagI(value);
 
1652
      LOperand* value = UseRegisterAtStart(val);
 
1653
      if (val->CheckFlag(HInstruction::kUint32)) {
 
1654
        LNumberTagU* result = new(zone()) LNumberTagU(value);
1619
1655
        return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
 
1656
      } else if (val->HasRange() && val->range()->IsInSmiRange()) {
 
1657
        return DefineAsRegister(new(zone()) LSmiTag(value));
 
1658
      } else {
 
1659
        LNumberTagI* result = new(zone()) LNumberTagI(value);
 
1660
        return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1620
1661
      }
1621
1662
    } else {
1622
1663
      ASSERT(to.IsDouble());
1623
 
      LOperand* value = Use(instr->value());
1624
 
      return DefineAsRegister(new LInteger32ToDouble(value));
 
1664
      if (instr->value()->CheckFlag(HInstruction::kUint32)) {
 
1665
        return DefineAsRegister(
 
1666
            new(zone()) LUint32ToDouble(UseRegister(instr->value())));
 
1667
      } else {
 
1668
        return DefineAsRegister(
 
1669
            new(zone()) LInteger32ToDouble(Use(instr->value())));
 
1670
      }
1625
1671
    }
1626
1672
  }
1627
1673
  UNREACHABLE();
1631
1677
 
1632
1678
LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1633
1679
  LOperand* value = UseRegisterAtStart(instr->value());
1634
 
  return AssignEnvironment(new LCheckNonSmi(value));
 
1680
  return AssignEnvironment(new(zone()) LCheckNonSmi(value));
1635
1681
}
1636
1682
 
1637
1683
 
1638
1684
LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1639
1685
  LOperand* value = UseRegisterAtStart(instr->value());
1640
 
  LInstruction* result = new LCheckInstanceType(value);
 
1686
  LInstruction* result = new(zone()) LCheckInstanceType(value);
1641
1687
  return AssignEnvironment(result);
1642
1688
}
1643
1689
 
1645
1691
LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
1646
1692
  LOperand* temp1 = TempRegister();
1647
1693
  LOperand* temp2 = TempRegister();
1648
 
  LInstruction* result = new LCheckPrototypeMaps(temp1, temp2);
 
1694
  LInstruction* result = new(zone()) LCheckPrototypeMaps(temp1, temp2);
1649
1695
  return AssignEnvironment(result);
1650
1696
}
1651
1697
 
1652
1698
 
1653
1699
LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1654
1700
  LOperand* value = UseRegisterAtStart(instr->value());
1655
 
  return AssignEnvironment(new LCheckSmi(value));
 
1701
  return AssignEnvironment(new(zone()) LCheckSmi(value));
1656
1702
}
1657
1703
 
1658
1704
 
1659
1705
LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1660
1706
  LOperand* value = UseRegisterAtStart(instr->value());
1661
 
  return AssignEnvironment(new LCheckFunction(value));
 
1707
  return AssignEnvironment(new(zone()) LCheckFunction(value));
1662
1708
}
1663
1709
 
1664
1710
 
1665
 
LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
 
1711
LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
1666
1712
  LOperand* value = UseRegisterAtStart(instr->value());
1667
 
  LInstruction* result = new LCheckMap(value);
 
1713
  LInstruction* result = new(zone()) LCheckMaps(value);
1668
1714
  return AssignEnvironment(result);
1669
1715
}
1670
1716
 
1674
1720
  Representation input_rep = value->representation();
1675
1721
  LOperand* reg = UseRegister(value);
1676
1722
  if (input_rep.IsDouble()) {
1677
 
    return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(d11)));
 
1723
    return DefineAsRegister(new(zone()) LClampDToUint8(reg, FixedTemp(d11)));
1678
1724
  } else if (input_rep.IsInteger32()) {
1679
 
    return DefineAsRegister(new LClampIToUint8(reg));
 
1725
    return DefineAsRegister(new(zone()) LClampIToUint8(reg));
1680
1726
  } else {
1681
1727
    ASSERT(input_rep.IsTagged());
1682
1728
    // Register allocator doesn't (yet) support allocation of double
1683
1729
    // temps. Reserve d1 explicitly.
1684
 
    LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(d11));
 
1730
    LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(d11));
1685
1731
    return AssignEnvironment(DefineAsRegister(result));
1686
1732
  }
1687
1733
}
1688
1734
 
1689
1735
 
1690
 
LInstruction* LChunkBuilder::DoToInt32(HToInt32* instr) {
1691
 
  HValue* value = instr->value();
1692
 
  Representation input_rep = value->representation();
1693
 
  LOperand* reg = UseRegister(value);
1694
 
  if (input_rep.IsDouble()) {
1695
 
    LOperand* temp1 = TempRegister();
1696
 
    LOperand* temp2 = TempRegister();
1697
 
    LDoubleToI* res = new LDoubleToI(reg, temp1, temp2);
1698
 
    return AssignEnvironment(DefineAsRegister(res));
1699
 
  } else if (input_rep.IsInteger32()) {
1700
 
    // Canonicalization should already have removed the hydrogen instruction in
1701
 
    // this case, since it is a noop.
1702
 
    UNREACHABLE();
1703
 
    return NULL;
1704
 
  } else {
1705
 
    ASSERT(input_rep.IsTagged());
1706
 
    LOperand* temp1 = TempRegister();
1707
 
    LOperand* temp2 = TempRegister();
1708
 
    LOperand* temp3 = FixedTemp(d11);
1709
 
    LTaggedToI* res = new LTaggedToI(reg, temp1, temp2, temp3);
1710
 
    return AssignEnvironment(DefineSameAsFirst(res));
1711
 
  }
1712
 
}
1713
 
 
1714
 
 
1715
1736
LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1716
 
  return new LReturn(UseFixed(instr->value(), r0));
 
1737
  return new(zone()) LReturn(UseFixed(instr->value(), r0));
1717
1738
}
1718
1739
 
1719
1740
 
1720
1741
LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1721
1742
  Representation r = instr->representation();
1722
1743
  if (r.IsInteger32()) {
1723
 
    return DefineAsRegister(new LConstantI);
 
1744
    return DefineAsRegister(new(zone()) LConstantI);
1724
1745
  } else if (r.IsDouble()) {
1725
 
    return DefineAsRegister(new LConstantD);
 
1746
    return DefineAsRegister(new(zone()) LConstantD);
1726
1747
  } else if (r.IsTagged()) {
1727
 
    return DefineAsRegister(new LConstantT);
 
1748
    return DefineAsRegister(new(zone()) LConstantT);
1728
1749
  } else {
1729
1750
    UNREACHABLE();
1730
1751
    return NULL;
1733
1754
 
1734
1755
 
1735
1756
LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
1736
 
  LLoadGlobalCell* result = new LLoadGlobalCell;
1737
 
  return instr->check_hole_value()
 
1757
  LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
 
1758
  return instr->RequiresHoleCheck()
1738
1759
      ? AssignEnvironment(DefineAsRegister(result))
1739
1760
      : DefineAsRegister(result);
1740
1761
}
1742
1763
 
1743
1764
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1744
1765
  LOperand* global_object = UseFixed(instr->global_object(), r0);
1745
 
  LLoadGlobalGeneric* result = new LLoadGlobalGeneric(global_object);
 
1766
  LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object);
1746
1767
  return MarkAsCall(DefineFixed(result, r0), instr);
1747
1768
}
1748
1769
 
1749
1770
 
1750
1771
LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
1751
 
  if (instr->check_hole_value()) {
1752
 
    LOperand* temp = TempRegister();
1753
 
    LOperand* value = UseRegister(instr->value());
1754
 
    return AssignEnvironment(new LStoreGlobalCell(value, temp));
1755
 
  } else {
1756
 
    LOperand* value = UseRegisterAtStart(instr->value());
1757
 
    return new LStoreGlobalCell(value, NULL);
1758
 
  }
 
1772
  LOperand* value = UseRegister(instr->value());
 
1773
  // Use a temp to check the value in the cell in the case where we perform
 
1774
  // a hole check.
 
1775
  return instr->RequiresHoleCheck()
 
1776
      ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister()))
 
1777
      : new(zone()) LStoreGlobalCell(value, NULL);
1759
1778
}
1760
1779
 
1761
1780
 
1763
1782
  LOperand* global_object = UseFixed(instr->global_object(), r1);
1764
1783
  LOperand* value = UseFixed(instr->value(), r0);
1765
1784
  LStoreGlobalGeneric* result =
1766
 
      new LStoreGlobalGeneric(global_object, value);
 
1785
      new(zone()) LStoreGlobalGeneric(global_object, value);
1767
1786
  return MarkAsCall(result, instr);
1768
1787
}
1769
1788
 
1770
1789
 
1771
1790
LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1772
1791
  LOperand* context = UseRegisterAtStart(instr->value());
1773
 
  return DefineAsRegister(new LLoadContextSlot(context));
 
1792
  LInstruction* result =
 
1793
      DefineAsRegister(new(zone()) LLoadContextSlot(context));
 
1794
  return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1774
1795
}
1775
1796
 
1776
1797
 
1784
1805
    context = UseRegister(instr->context());
1785
1806
    value = UseRegister(instr->value());
1786
1807
  }
1787
 
  return new LStoreContextSlot(context, value);
 
1808
  LInstruction* result = new(zone()) LStoreContextSlot(context, value);
 
1809
  return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1788
1810
}
1789
1811
 
1790
1812
 
1791
1813
LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1792
1814
  return DefineAsRegister(
1793
 
      new LLoadNamedField(UseRegisterAtStart(instr->object())));
 
1815
      new(zone()) LLoadNamedField(UseRegisterAtStart(instr->object())));
1794
1816
}
1795
1817
 
1796
1818
 
1799
1821
  ASSERT(instr->representation().IsTagged());
1800
1822
  if (instr->need_generic()) {
1801
1823
    LOperand* obj = UseFixed(instr->object(), r0);
1802
 
    LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
 
1824
    LLoadNamedFieldPolymorphic* result =
 
1825
        new(zone()) LLoadNamedFieldPolymorphic(obj);
1803
1826
    return MarkAsCall(DefineFixed(result, r0), instr);
1804
1827
  } else {
1805
1828
    LOperand* obj = UseRegisterAtStart(instr->object());
1806
 
    LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
 
1829
    LLoadNamedFieldPolymorphic* result =
 
1830
        new(zone()) LLoadNamedFieldPolymorphic(obj);
1807
1831
    return AssignEnvironment(DefineAsRegister(result));
1808
1832
  }
1809
1833
}
1811
1835
 
1812
1836
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1813
1837
  LOperand* object = UseFixed(instr->object(), r0);
1814
 
  LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0);
 
1838
  LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), r0);
1815
1839
  return MarkAsCall(result, instr);
1816
1840
}
1817
1841
 
1819
1843
LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1820
1844
    HLoadFunctionPrototype* instr) {
1821
1845
  return AssignEnvironment(DefineAsRegister(
1822
 
      new LLoadFunctionPrototype(UseRegister(instr->function()))));
 
1846
      new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
1823
1847
}
1824
1848
 
1825
1849
 
1826
1850
LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1827
1851
  LOperand* input = UseRegisterAtStart(instr->value());
1828
 
  return DefineAsRegister(new LLoadElements(input));
 
1852
  return DefineAsRegister(new(zone()) LLoadElements(input));
1829
1853
}
1830
1854
 
1831
1855
 
1832
1856
LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
1833
1857
    HLoadExternalArrayPointer* instr) {
1834
1858
  LOperand* input = UseRegisterAtStart(instr->value());
1835
 
  return DefineAsRegister(new LLoadExternalArrayPointer(input));
 
1859
  return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
1836
1860
}
1837
1861
 
1838
1862
 
1839
1863
LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1840
1864
    HLoadKeyedFastElement* instr) {
1841
1865
  ASSERT(instr->representation().IsTagged());
1842
 
  ASSERT(instr->key()->representation().IsInteger32());
 
1866
  ASSERT(instr->key()->representation().IsInteger32() ||
 
1867
         instr->key()->representation().IsTagged());
1843
1868
  LOperand* obj = UseRegisterAtStart(instr->object());
1844
 
  LOperand* key = UseRegisterAtStart(instr->key());
1845
 
  LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
1846
 
  return AssignEnvironment(DefineAsRegister(result));
 
1869
  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
 
1870
  LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
 
1871
  if (instr->RequiresHoleCheck()) AssignEnvironment(result);
 
1872
  return DefineAsRegister(result);
1847
1873
}
1848
1874
 
1849
1875
 
1850
1876
LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
1851
1877
    HLoadKeyedFastDoubleElement* instr) {
1852
1878
  ASSERT(instr->representation().IsDouble());
1853
 
  ASSERT(instr->key()->representation().IsInteger32());
 
1879
  ASSERT(instr->key()->representation().IsInteger32() ||
 
1880
         instr->key()->representation().IsTagged());
1854
1881
  LOperand* elements = UseTempRegister(instr->elements());
1855
1882
  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1856
1883
  LLoadKeyedFastDoubleElement* result =
1857
 
      new LLoadKeyedFastDoubleElement(elements, key);
 
1884
      new(zone()) LLoadKeyedFastDoubleElement(elements, key);
1858
1885
  return AssignEnvironment(DefineAsRegister(result));
1859
1886
}
1860
1887
 
1862
1889
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
1863
1890
    HLoadKeyedSpecializedArrayElement* instr) {
1864
1891
  ElementsKind elements_kind = instr->elements_kind();
1865
 
  Representation representation(instr->representation());
1866
1892
  ASSERT(
1867
 
      (representation.IsInteger32() &&
 
1893
      (instr->representation().IsInteger32() &&
1868
1894
       (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
1869
1895
       (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
1870
 
      (representation.IsDouble() &&
 
1896
      (instr->representation().IsDouble() &&
1871
1897
       ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
1872
1898
       (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
1873
 
  ASSERT(instr->key()->representation().IsInteger32());
 
1899
  ASSERT(instr->key()->representation().IsInteger32() ||
 
1900
         instr->key()->representation().IsTagged());
1874
1901
  LOperand* external_pointer = UseRegister(instr->external_pointer());
1875
1902
  LOperand* key = UseRegisterOrConstant(instr->key());
1876
1903
  LLoadKeyedSpecializedArrayElement* result =
1877
 
      new LLoadKeyedSpecializedArrayElement(external_pointer, key);
 
1904
      new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
1878
1905
  LInstruction* load_instr = DefineAsRegister(result);
1879
1906
  // An unsigned int array load might overflow and cause a deopt, make sure it
1880
1907
  // has an environment.
1888
1915
  LOperand* key = UseFixed(instr->key(), r0);
1889
1916
 
1890
1917
  LInstruction* result =
1891
 
      DefineFixed(new LLoadKeyedGeneric(object, key), r0);
 
1918
      DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), r0);
1892
1919
  return MarkAsCall(result, instr);
1893
1920
}
1894
1921
 
1898
1925
  bool needs_write_barrier = instr->NeedsWriteBarrier();
1899
1926
  ASSERT(instr->value()->representation().IsTagged());
1900
1927
  ASSERT(instr->object()->representation().IsTagged());
1901
 
  ASSERT(instr->key()->representation().IsInteger32());
 
1928
  ASSERT(instr->key()->representation().IsInteger32() ||
 
1929
         instr->key()->representation().IsTagged());
1902
1930
 
1903
1931
  LOperand* obj = UseTempRegister(instr->object());
1904
1932
  LOperand* val = needs_write_barrier
1907
1935
  LOperand* key = needs_write_barrier
1908
1936
      ? UseTempRegister(instr->key())
1909
1937
      : UseRegisterOrConstantAtStart(instr->key());
1910
 
 
1911
 
  return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val));
 
1938
  return new(zone()) LStoreKeyedFastElement(obj, key, val);
1912
1939
}
1913
1940
 
1914
1941
 
1916
1943
    HStoreKeyedFastDoubleElement* instr) {
1917
1944
  ASSERT(instr->value()->representation().IsDouble());
1918
1945
  ASSERT(instr->elements()->representation().IsTagged());
1919
 
  ASSERT(instr->key()->representation().IsInteger32());
 
1946
  ASSERT(instr->key()->representation().IsInteger32() ||
 
1947
         instr->key()->representation().IsTagged());
1920
1948
 
1921
1949
  LOperand* elements = UseRegisterAtStart(instr->elements());
1922
1950
  LOperand* val = UseTempRegister(instr->value());
1923
1951
  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1924
1952
 
1925
 
  return new LStoreKeyedFastDoubleElement(elements, key, val);
 
1953
  return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
1926
1954
}
1927
1955
 
1928
1956
 
1929
1957
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
1930
1958
    HStoreKeyedSpecializedArrayElement* instr) {
1931
 
  Representation representation(instr->value()->representation());
1932
1959
  ElementsKind elements_kind = instr->elements_kind();
1933
1960
  ASSERT(
1934
 
      (representation.IsInteger32() &&
 
1961
      (instr->value()->representation().IsInteger32() &&
1935
1962
       (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
1936
1963
       (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
1937
 
      (representation.IsDouble() &&
 
1964
      (instr->value()->representation().IsDouble() &&
1938
1965
       ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
1939
1966
       (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
1940
1967
  ASSERT(instr->external_pointer()->representation().IsExternal());
1941
 
  ASSERT(instr->key()->representation().IsInteger32());
 
1968
  ASSERT(instr->key()->representation().IsInteger32() ||
 
1969
         instr->key()->representation().IsTagged());
1942
1970
 
1943
1971
  LOperand* external_pointer = UseRegister(instr->external_pointer());
1944
1972
  bool val_is_temp_register =
1949
1977
      : UseRegister(instr->value());
1950
1978
  LOperand* key = UseRegisterOrConstant(instr->key());
1951
1979
 
1952
 
  return new LStoreKeyedSpecializedArrayElement(external_pointer,
1953
 
                                                key,
1954
 
                                                val);
 
1980
  return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
 
1981
                                                        key,
 
1982
                                                        val);
1955
1983
}
1956
1984
 
1957
1985
 
1964
1992
  ASSERT(instr->key()->representation().IsTagged());
1965
1993
  ASSERT(instr->value()->representation().IsTagged());
1966
1994
 
1967
 
  return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr);
 
1995
  return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr);
 
1996
}
 
1997
 
 
1998
 
 
1999
LInstruction* LChunkBuilder::DoTransitionElementsKind(
 
2000
    HTransitionElementsKind* instr) {
 
2001
  ElementsKind from_kind = instr->original_map()->elements_kind();
 
2002
  ElementsKind to_kind = instr->transitioned_map()->elements_kind();
 
2003
  if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
 
2004
    LOperand* object = UseRegister(instr->object());
 
2005
    LOperand* new_map_reg = TempRegister();
 
2006
    LTransitionElementsKind* result =
 
2007
        new(zone()) LTransitionElementsKind(object, new_map_reg, NULL);
 
2008
    return DefineSameAsFirst(result);
 
2009
  } else {
 
2010
    LOperand* object = UseFixed(instr->object(), r0);
 
2011
    LOperand* fixed_object_reg = FixedTemp(r2);
 
2012
    LOperand* new_map_reg = FixedTemp(r3);
 
2013
    LTransitionElementsKind* result =
 
2014
        new(zone()) LTransitionElementsKind(object,
 
2015
                                            new_map_reg,
 
2016
                                            fixed_object_reg);
 
2017
    return MarkAsCall(DefineFixed(result, r0), instr);
 
2018
  }
1968
2019
}
1969
2020
 
1970
2021
 
1971
2022
LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
1972
2023
  bool needs_write_barrier = instr->NeedsWriteBarrier();
 
2024
  bool needs_write_barrier_for_map = !instr->transition().is_null() &&
 
2025
      instr->NeedsWriteBarrierForMap();
1973
2026
 
1974
 
  LOperand* obj = needs_write_barrier
1975
 
      ? UseTempRegister(instr->object())
1976
 
      : UseRegisterAtStart(instr->object());
 
2027
  LOperand* obj;
 
2028
  if (needs_write_barrier) {
 
2029
    obj = instr->is_in_object()
 
2030
        ? UseRegister(instr->object())
 
2031
        : UseTempRegister(instr->object());
 
2032
  } else {
 
2033
    obj = needs_write_barrier_for_map
 
2034
        ? UseRegister(instr->object())
 
2035
        : UseRegisterAtStart(instr->object());
 
2036
  }
1977
2037
 
1978
2038
  LOperand* val = needs_write_barrier
1979
2039
      ? UseTempRegister(instr->value())
1980
2040
      : UseRegister(instr->value());
1981
2041
 
1982
 
  return new LStoreNamedField(obj, val);
 
2042
  // We need a temporary register for write barrier of the map field.
 
2043
  LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
 
2044
 
 
2045
  return new(zone()) LStoreNamedField(obj, val, temp);
1983
2046
}
1984
2047
 
1985
2048
 
1987
2050
  LOperand* obj = UseFixed(instr->object(), r1);
1988
2051
  LOperand* val = UseFixed(instr->value(), r0);
1989
2052
 
1990
 
  LInstruction* result = new LStoreNamedGeneric(obj, val);
 
2053
  LInstruction* result = new(zone()) LStoreNamedGeneric(obj, val);
1991
2054
  return MarkAsCall(result, instr);
1992
2055
}
1993
2056
 
1995
2058
LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
1996
2059
  LOperand* left = UseRegisterAtStart(instr->left());
1997
2060
  LOperand* right = UseRegisterAtStart(instr->right());
1998
 
  return MarkAsCall(DefineFixed(new LStringAdd(left, right), r0), instr);
 
2061
  return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), r0),
 
2062
                    instr);
1999
2063
}
2000
2064
 
2001
2065
 
2002
2066
LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2003
2067
  LOperand* string = UseTempRegister(instr->string());
2004
2068
  LOperand* index = UseTempRegister(instr->index());
2005
 
  LStringCharCodeAt* result = new LStringCharCodeAt(string, index);
 
2069
  LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index);
2006
2070
  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2007
2071
}
2008
2072
 
2009
2073
 
2010
2074
LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2011
2075
  LOperand* char_code = UseRegister(instr->value());
2012
 
  LStringCharFromCode* result = new LStringCharFromCode(char_code);
 
2076
  LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code);
2013
2077
  return AssignPointerMap(DefineAsRegister(result));
2014
2078
}
2015
2079
 
2016
2080
 
2017
2081
LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
2018
2082
  LOperand* string = UseRegisterAtStart(instr->value());
2019
 
  return DefineAsRegister(new LStringLength(string));
 
2083
  return DefineAsRegister(new(zone()) LStringLength(string));
 
2084
}
 
2085
 
 
2086
 
 
2087
LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
 
2088
  LAllocateObject* result =
 
2089
      new(zone()) LAllocateObject(TempRegister(), TempRegister());
 
2090
  return AssignPointerMap(DefineAsRegister(result));
 
2091
}
 
2092
 
 
2093
 
 
2094
LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
 
2095
  return MarkAsCall(DefineFixed(new(zone()) LFastLiteral, r0), instr);
2020
2096
}
2021
2097
 
2022
2098
 
2023
2099
LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
2024
 
  return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr);
 
2100
  return MarkAsCall(DefineFixed(new(zone()) LArrayLiteral, r0), instr);
2025
2101
}
2026
2102
 
2027
2103
 
2028
2104
LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
2029
 
  return MarkAsCall(DefineFixed(new LObjectLiteral, r0), instr);
 
2105
  return MarkAsCall(DefineFixed(new(zone()) LObjectLiteral, r0), instr);
2030
2106
}
2031
2107
 
2032
2108
 
2033
2109
LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2034
 
  return MarkAsCall(DefineFixed(new LRegExpLiteral, r0), instr);
 
2110
  return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, r0), instr);
2035
2111
}
2036
2112
 
2037
2113
 
2038
2114
LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2039
 
  return MarkAsCall(DefineFixed(new LFunctionLiteral, r0), instr);
 
2115
  return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, r0), instr);
2040
2116
}
2041
2117
 
2042
2118
 
2043
2119
LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
2044
2120
  LOperand* object = UseFixed(instr->object(), r0);
2045
2121
  LOperand* key = UseFixed(instr->key(), r1);
2046
 
  LDeleteProperty* result = new LDeleteProperty(object, key);
 
2122
  LDeleteProperty* result = new(zone()) LDeleteProperty(object, key);
2047
2123
  return MarkAsCall(DefineFixed(result, r0), instr);
2048
2124
}
2049
2125
 
2050
2126
 
2051
2127
LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
 
2128
  ASSERT(argument_count_ == 0);
2052
2129
  allocator_->MarkAsOsrEntry();
2053
2130
  current_block_->last_environment()->set_ast_id(instr->ast_id());
2054
 
  return AssignEnvironment(new LOsrEntry);
 
2131
  return AssignEnvironment(new(zone()) LOsrEntry);
2055
2132
}
2056
2133
 
2057
2134
 
2058
2135
LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2059
2136
  int spill_index = chunk()->GetParameterStackSlot(instr->index());
2060
 
  return DefineAsSpilled(new LParameter, spill_index);
 
2137
  return DefineAsSpilled(new(zone()) LParameter, spill_index);
2061
2138
}
2062
2139
 
2063
2140
 
2067
2144
    Abort("Too many spill slots needed for OSR");
2068
2145
    spill_index = 0;
2069
2146
  }
2070
 
  return DefineAsSpilled(new LUnknownOSRValue, spill_index);
 
2147
  return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
2071
2148
}
2072
2149
 
2073
2150
 
2074
2151
LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2075
2152
  argument_count_ -= instr->argument_count();
2076
 
  return MarkAsCall(DefineFixed(new LCallStub, r0), instr);
 
2153
  return MarkAsCall(DefineFixed(new(zone()) LCallStub, r0), instr);
2077
2154
}
2078
2155
 
2079
2156
 
2087
2164
 
2088
2165
 
2089
2166
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2090
 
  LOperand* arguments = UseRegister(instr->arguments());
 
2167
  LOperand* args = UseRegister(instr->arguments());
2091
2168
  LOperand* length = UseTempRegister(instr->length());
2092
2169
  LOperand* index = UseRegister(instr->index());
2093
 
  LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index);
2094
 
  return AssignEnvironment(DefineAsRegister(result));
 
2170
  return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
2095
2171
}
2096
2172
 
2097
2173
 
2098
2174
LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2099
2175
  LOperand* object = UseFixed(instr->value(), r0);
2100
 
  LToFastProperties* result = new LToFastProperties(object);
 
2176
  LToFastProperties* result = new(zone()) LToFastProperties(object);
2101
2177
  return MarkAsCall(DefineFixed(result, r0), instr);
2102
2178
}
2103
2179
 
2104
2180
 
2105
2181
LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2106
 
  LTypeof* result = new LTypeof(UseFixed(instr->value(), r0));
 
2182
  LTypeof* result = new(zone()) LTypeof(UseFixed(instr->value(), r0));
2107
2183
  return MarkAsCall(DefineFixed(result, r0), instr);
2108
2184
}
2109
2185
 
2110
2186
 
2111
2187
LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2112
 
  return new LTypeofIsAndBranch(UseTempRegister(instr->value()));
 
2188
  return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2113
2189
}
2114
2190
 
2115
2191
 
2116
2192
LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2117
2193
    HIsConstructCallAndBranch* instr) {
2118
 
  return new LIsConstructCallAndBranch(TempRegister());
 
2194
  return new(zone()) LIsConstructCallAndBranch(TempRegister());
2119
2195
}
2120
2196
 
2121
2197
 
2138
2214
  // If there is an instruction pending deoptimization environment create a
2139
2215
  // lazy bailout instruction to capture the environment.
2140
2216
  if (pending_deoptimization_ast_id_ == instr->ast_id()) {
2141
 
    LInstruction* result = new LLazyBailout;
 
2217
    LInstruction* result = new(zone()) LLazyBailout;
2142
2218
    result = AssignEnvironment(result);
 
2219
    // Store the lazy deopt environment with the instruction if needed. Right
 
2220
    // now it is only used for LInstanceOfKnownGlobal.
2143
2221
    instruction_pending_deoptimization_environment_->
2144
 
        set_deoptimization_environment(result->environment());
2145
 
    ClearInstructionPendingDeoptimizationEnvironment();
 
2222
        SetDeferredLazyDeoptimizationEnvironment(result->environment());
 
2223
    instruction_pending_deoptimization_environment_ = NULL;
 
2224
    pending_deoptimization_ast_id_ = BailoutId::None();
2146
2225
    return result;
2147
2226
  }
2148
2227
 
2152
2231
 
2153
2232
LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2154
2233
  if (instr->is_function_entry()) {
2155
 
    return MarkAsCall(new LStackCheck, instr);
 
2234
    return MarkAsCall(new(zone()) LStackCheck, instr);
2156
2235
  } else {
2157
2236
    ASSERT(instr->is_backwards_branch());
2158
 
    return AssignEnvironment(AssignPointerMap(new LStackCheck));
 
2237
    return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
2159
2238
  }
2160
2239
}
2161
2240
 
2164
2243
  HEnvironment* outer = current_block_->last_environment();
2165
2244
  HConstant* undefined = graph()->GetConstantUndefined();
2166
2245
  HEnvironment* inner = outer->CopyForInlining(instr->closure(),
 
2246
                                               instr->arguments_count(),
2167
2247
                                               instr->function(),
2168
2248
                                               undefined,
2169
 
                                               instr->call_kind());
 
2249
                                               instr->call_kind(),
 
2250
                                               instr->inlining_kind());
 
2251
  if (instr->arguments_var() != NULL) {
 
2252
    inner->Bind(instr->arguments_var(), graph()->GetArgumentsObject());
 
2253
  }
 
2254
  inner->set_entry(instr);
2170
2255
  current_block_->UpdateEnvironment(inner);
2171
2256
  chunk_->AddInlinedClosure(instr->closure());
2172
2257
  return NULL;
2174
2259
 
2175
2260
 
2176
2261
LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2177
 
  HEnvironment* outer = current_block_->last_environment()->outer();
 
2262
  LInstruction* pop = NULL;
 
2263
 
 
2264
  HEnvironment* env = current_block_->last_environment();
 
2265
 
 
2266
  if (env->entry()->arguments_pushed()) {
 
2267
    int argument_count = env->arguments_environment()->parameter_count();
 
2268
    pop = new(zone()) LDrop(argument_count);
 
2269
    argument_count_ -= argument_count;
 
2270
  }
 
2271
 
 
2272
  HEnvironment* outer = current_block_->last_environment()->
 
2273
      DiscardInlined(false);
2178
2274
  current_block_->UpdateEnvironment(outer);
2179
 
  return NULL;
 
2275
 
 
2276
  return pop;
2180
2277
}
2181
2278
 
2182
2279
 
2183
2280
LInstruction* LChunkBuilder::DoIn(HIn* instr) {
2184
2281
  LOperand* key = UseRegisterAtStart(instr->key());
2185
2282
  LOperand* object = UseRegisterAtStart(instr->object());
2186
 
  LIn* result = new LIn(key, object);
 
2283
  LIn* result = new(zone()) LIn(key, object);
2187
2284
  return MarkAsCall(DefineFixed(result, r0), instr);
2188
2285
}
2189
2286
 
2190
2287
 
 
2288
LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
 
2289
  LOperand* object = UseFixed(instr->enumerable(), r0);
 
2290
  LForInPrepareMap* result = new(zone()) LForInPrepareMap(object);
 
2291
  return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
 
2292
}
 
2293
 
 
2294
 
 
2295
LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
 
2296
  LOperand* map = UseRegister(instr->map());
 
2297
  return AssignEnvironment(DefineAsRegister(new(zone()) LForInCacheArray(map)));
 
2298
}
 
2299
 
 
2300
 
 
2301
LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
 
2302
  LOperand* value = UseRegisterAtStart(instr->value());
 
2303
  LOperand* map = UseRegisterAtStart(instr->map());
 
2304
  return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
 
2305
}
 
2306
 
 
2307
 
 
2308
LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
 
2309
  LOperand* object = UseRegister(instr->object());
 
2310
  LOperand* index = UseRegister(instr->index());
 
2311
  return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index));
 
2312
}
 
2313
 
 
2314
 
2191
2315
} }  // namespace v8::internal