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);
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);
120
void LInstruction::PrintOutputOperandTo(StringStream* stream) {
121
if (HasResult()) result()->PrintTo(stream);
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);
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());
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());
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());
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());
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());
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());
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());
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());
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());
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(),
282
293
void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
283
294
stream->Add("/%s ", hydrogen()->OpName());
284
InputAt(0)->PrintTo(stream);
295
value()->PrintTo(stream);
288
299
void LLoadContextSlot::PrintDataTo(StringStream* stream) {
289
InputAt(0)->PrintTo(stream);
300
context()->PrintTo(stream);
290
301
stream->Add("[%d]", slot_index());
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);
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());
393
LChunk::LChunk(CompilationInfo* info, HGraph* graph)
394
: spill_slot_count_(0),
399
inlined_closures_(1) {
402
void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
403
object()->PrintTo(stream);
404
stream->Add(" %p -> %p", *original_map(), *transitioned_map());
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_++;
410
LOperand* LChunk::GetNextSpillSlot(bool is_double) {
415
LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) {
411
416
int index = GetNextSpillIndex(is_double);
413
return LDoubleStackSlot::Create(index);
415
return LStackSlot::Create(index);
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);
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);
438
LGap* gap = LGap::cast(cur);
439
if (!gap->IsRedundant()) {
440
can_eliminate = false;
443
can_eliminate = false;
448
label->set_replacement(GetLabel(goto_instr->block_id()));
456
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
457
LInstructionGap* gap = new LInstructionGap(block);
459
if (instr->IsControl()) {
460
instructions_.Add(gap);
461
index = instructions_.length();
462
instructions_.Add(instr);
464
index = instructions_.length();
465
instructions_.Add(instr);
466
instructions_.Add(gap);
468
if (instr->HasPointerMap()) {
469
pointer_maps_.Add(instr->pointer_map());
470
instr->pointer_map()->set_lithium_position(index);
475
LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
476
return LConstantOperand::Create(constant->id());
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
485
int result = index - info()->scope()->num_parameters() - 1;
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) *
498
LGap* LChunk::GetGapAt(int index) const {
499
return LGap::cast(instructions_[index]);
503
bool LChunk::IsGapAt(int index) const {
504
return instructions_[index]->IsGap();
508
int LChunk::NearestGapPos(int index) const {
509
while (!IsGapAt(index)) index--;
514
void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
515
GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to);
519
Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
520
return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
524
Representation LChunk::LookupLiteralRepresentation(
525
LConstantOperand* operand) const {
526
return graph_->LookupValue(operand->index())->representation();
530
LChunk* LChunkBuilder::Build() {
418
return LDoubleStackSlot::Create(index, zone());
420
return LStackSlot::Create(index, zone());
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++) {
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);
553
va_start(arguments, format);
554
OS::VPrint(format, arguments);
442
void LChunkBuilder::Abort(const char* reason) {
443
info()->set_bailout_reason(reason);
558
444
status_ = ABORTED;
562
LRegister* LChunkBuilder::ToOperand(Register reg) {
563
return LRegister::Create(Register::ToAllocationIndex(reg));
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));
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));
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));
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));
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));
606
487
LOperand* LChunkBuilder::Use(HValue* value) {
607
return Use(value, new LUnallocated(LUnallocated::NONE));
488
return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
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));
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);
671
552
template<int I, int T>
672
LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr) {
673
return Define(instr, new LUnallocated(LUnallocated::NONE));
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));
556
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
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));
564
new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
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));
572
new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
712
590
LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
713
591
HEnvironment* hydrogen_env = current_block_->last_environment();
714
instr->set_environment(CreateEnvironment(hydrogen_env));
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;
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));
765
LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
766
instr->MarkAsSaveDoubles();
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()));
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.");
785
648
LOperand* LChunkBuilder::FixedTemp(Register reg) {
786
649
LUnallocated* operand = ToUnallocated(reg);
787
allocator_->RecordTemporary(operand);
650
ASSERT(operand->HasFixedPolicy());
792
655
LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) {
793
656
LUnallocated* operand = ToUnallocated(reg);
794
allocator_->RecordTemporary(operand);
657
ASSERT(operand->HasFixedPolicy());
799
662
LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
800
return new LLabel(instr->block());
663
return new(zone()) LLabel(instr->block());
804
667
LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
805
return AssignEnvironment(new LDeoptimize);
668
return AssignEnvironment(new(zone()) LDeoptimize);
809
672
LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
810
return AssignEnvironment(new LDeoptimize);
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());
820
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
821
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
822
return DefineAsRegister(new LBitI(op, left, right));
824
ASSERT(instr->representation().IsTagged());
825
ASSERT(instr->left()->representation().IsTagged());
826
ASSERT(instr->right()->representation().IsTagged());
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);
673
return AssignEnvironment(new(zone()) LDeoptimize);
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;
869
for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
870
if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
708
if (op == Token::SHR && constant_value == 0) {
709
if (FLAG_opt_safe_uint32_operations) {
710
does_deopt = !instr->CheckFlag(HInstruction::kUint32);
712
for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
713
if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
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;
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;
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(),
1006
hydrogen_env->parameter_count(),
1010
int argument_index = 0;
853
LEnvironment* result = new(zone()) LEnvironment(
854
hydrogen_env->closure(),
855
hydrogen_env->frame_type(),
857
hydrogen_env->parameter_count(),
861
hydrogen_env->entry(),
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;
1030
889
LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
1031
return new LGoto(instr->FirstSuccessor()->block_id());
890
return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
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());
1043
return AssignEnvironment(new LBranch(UseRegister(v)));
900
return new(zone()) LGoto(successor->block_id());
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);
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);
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));
1061
930
LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1062
return DefineAsRegister(new LArgumentsElements);
931
return DefineAsRegister(new(zone()) LArgumentsElements);
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);
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),
1078
948
return MarkAsCall(DefineFixed(result, r0), instr);
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));
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,
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);
1102
980
LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
1103
return instr->HasNoUses() ? NULL : DefineAsRegister(new LThisFunction);
981
return instr->HasNoUses()
983
: DefineAsRegister(new(zone()) LThisFunction);
1107
987
LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1108
return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
988
return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
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));
998
LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
999
return MarkAsCall(new(zone()) LDeclareGlobals, instr);
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));
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));
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);
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);
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);
1152
1042
LOperand* input = UseRegisterAtStart(instr->value());
1153
LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
1154
LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
1044
LOperand* temp = (op == kMathRound) ? FixedTemp(d3) : NULL;
1045
LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
1157
1048
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
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);
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);
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);
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);
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);
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),
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);
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());
1131
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1132
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1133
return DefineAsRegister(new(zone()) LBitI(left, right));
1135
ASSERT(instr->representation().IsTagged());
1136
ASSERT(instr->left()->representation().IsTagged());
1137
ASSERT(instr->right()->representation().IsTagged());
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);
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())));
1247
LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
1248
return DoBit(Token::BIT_OR, instr);
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));
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)));
1271
1170
return DoArithmeticT(Token::DIV, instr);
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;
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.
1189
// <divisor with magic numbers> * <power of 2>
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;
1202
HValue* LChunkBuilder::SimplifiedDividendForMathFloorOfDiv(HValue* dividend) {
1203
// A value with an integer representation does not need to be transformed.
1204
if (dividend->representation().IsInteger32()) {
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();
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
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());
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)));
1276
1245
LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1277
1246
if (instr->representation().IsInteger32()) {
1278
1247
ASSERT(instr->left()->representation().IsInteger32());
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());
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());
1373
return DefineAsRegister(new(zone()) LMathMinMax(left, right));
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),
1397
1390
CAN_DEOPTIMIZE_EAGERLY);
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);
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);
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);
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);
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);
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);
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()));
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);
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);
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()));
1466
1476
LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1467
1477
HIsUndetectableAndBranch* instr) {
1468
1478
ASSERT(instr->value()->representation().IsTagged());
1469
return new LIsUndetectableAndBranch(UseRegisterAtStart(instr->value()),
1479
LOperand* value = UseRegisterAtStart(instr->value());
1480
return new(zone()) LIsUndetectableAndBranch(value, TempRegister());
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);
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);
1498
1521
LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1499
1522
HClassOfTestAndBranch* instr) {
1500
1523
ASSERT(instr->value()->representation().IsTagged());
1501
return new LClassOfTestAndBranch(UseTempRegister(instr->value()),
1524
LOperand* value = UseRegister(instr->value());
1525
return new(zone()) LClassOfTestAndBranch(value, TempRegister());
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));
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));
1542
LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1543
LOperand* map = UseRegisterAtStart(instr->value());
1544
return DefineAsRegister(new(zone()) LMapEnumLength(map));
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));
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);
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);
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));
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));
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;
1578
res = DefineSameAsFirst(new LSmiUntag(value, needs_check));
1614
if (instr->value()->type().IsSmi()) {
1615
res = DefineAsRegister(new(zone()) LSmiUntag(value, false));
1580
1617
LOperand* temp1 = TempRegister();
1581
1618
LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
1583
LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d11)
1585
res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3));
1620
LOperand* temp3 = FixedTemp(d11);
1621
res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
1586
1625
res = AssignEnvironment(res);
1596
1635
// Make sure that the temp and result_temp registers are
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);
1603
1642
ASSERT(to.IsInteger32());
1604
1643
LOperand* value = UseRegister(instr->value());
1606
new LDoubleToI(value,
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));
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));
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));
1659
LNumberTagI* result = new(zone()) LNumberTagI(value);
1660
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
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())));
1668
return DefineAsRegister(
1669
new(zone()) LInteger32ToDouble(Use(instr->value())));
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);
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));
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));
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);
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));
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));
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.
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));
1715
1736
LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1716
return new LReturn(UseFixed(instr->value(), r0));
1737
return new(zone()) LReturn(UseFixed(instr->value(), r0));
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);
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);
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));
1756
LOperand* value = UseRegisterAtStart(instr->value());
1757
return new LStoreGlobalCell(value, NULL);
1772
LOperand* value = UseRegister(instr->value());
1773
// Use a temp to check the value in the cell in the case where we perform
1775
return instr->RequiresHoleCheck()
1776
? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister()))
1777
: new(zone()) LStoreGlobalCell(value, NULL);
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()))));
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));
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));
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);
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));
1862
1889
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
1863
1890
HLoadKeyedSpecializedArrayElement* instr) {
1864
1891
ElementsKind elements_kind = instr->elements_kind();
1865
Representation representation(instr->representation());
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.
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());
1921
1949
LOperand* elements = UseRegisterAtStart(instr->elements());
1922
1950
LOperand* val = UseTempRegister(instr->value());
1923
1951
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1925
return new LStoreKeyedFastDoubleElement(elements, key, val);
1953
return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
1929
1957
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
1930
1958
HStoreKeyedSpecializedArrayElement* instr) {
1931
Representation representation(instr->value()->representation());
1932
1959
ElementsKind elements_kind = instr->elements_kind();
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());
1943
1971
LOperand* external_pointer = UseRegister(instr->external_pointer());
1944
1972
bool val_is_temp_register =
1964
1992
ASSERT(instr->key()->representation().IsTagged());
1965
1993
ASSERT(instr->value()->representation().IsTagged());
1967
return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr);
1995
return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr);
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);
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,
2017
return MarkAsCall(DefineFixed(result, r0), instr);
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();
1974
LOperand* obj = needs_write_barrier
1975
? UseTempRegister(instr->object())
1976
: UseRegisterAtStart(instr->object());
2028
if (needs_write_barrier) {
2029
obj = instr->is_in_object()
2030
? UseRegister(instr->object())
2031
: UseTempRegister(instr->object());
2033
obj = needs_write_barrier_for_map
2034
? UseRegister(instr->object())
2035
: UseRegisterAtStart(instr->object());
1978
2038
LOperand* val = needs_write_barrier
1979
2039
? UseTempRegister(instr->value())
1980
2040
: UseRegister(instr->value());
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;
2045
return new(zone()) LStoreNamedField(obj, val, temp);
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),
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)));
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));
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));
2087
LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
2088
LAllocateObject* result =
2089
new(zone()) LAllocateObject(TempRegister(), TempRegister());
2090
return AssignPointerMap(DefineAsRegister(result));
2094
LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
2095
return MarkAsCall(DefineFixed(new(zone()) LFastLiteral, r0), instr);
2023
2099
LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
2024
return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr);
2100
return MarkAsCall(DefineFixed(new(zone()) LArrayLiteral, r0), instr);
2028
2104
LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
2029
return MarkAsCall(DefineFixed(new LObjectLiteral, r0), instr);
2105
return MarkAsCall(DefineFixed(new(zone()) LObjectLiteral, r0), instr);
2033
2109
LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2034
return MarkAsCall(DefineFixed(new LRegExpLiteral, r0), instr);
2110
return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, r0), instr);
2038
2114
LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2039
return MarkAsCall(DefineFixed(new LFunctionLiteral, r0), instr);
2115
return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, r0), instr);
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);
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);
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);
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));
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);
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);
2111
2187
LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2112
return new LTypeofIsAndBranch(UseTempRegister(instr->value()));
2188
return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2116
2192
LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2117
2193
HIsConstructCallAndBranch* instr) {
2118
return new LIsConstructCallAndBranch(TempRegister());
2194
return new(zone()) LIsConstructCallAndBranch(TempRegister());
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();
2176
2261
LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2177
HEnvironment* outer = current_block_->last_environment()->outer();
2262
LInstruction* pop = NULL;
2264
HEnvironment* env = current_block_->last_environment();
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;
2272
HEnvironment* outer = current_block_->last_environment()->
2273
DiscardInlined(false);
2178
2274
current_block_->UpdateEnvironment(outer);
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);
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);
2295
LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2296
LOperand* map = UseRegister(instr->map());
2297
return AssignEnvironment(DefineAsRegister(new(zone()) LForInCacheArray(map)));
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));
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));
2191
2315
} } // namespace v8::internal