Revision f230a1cf deps/v8/src/mips/lithium-mips.cc
deps/v8/src/mips/lithium-mips.cc | ||
---|---|---|
417 | 417 |
} |
418 | 418 |
|
419 | 419 |
|
420 |
int LPlatformChunk::GetNextSpillIndex(bool is_double) {
|
|
420 |
int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
|
|
421 | 421 |
// Skip a slot if for a double-width slot. |
422 |
if (is_double) spill_slot_count_++;
|
|
422 |
if (kind == DOUBLE_REGISTERS) spill_slot_count_++;
|
|
423 | 423 |
return spill_slot_count_++; |
424 | 424 |
} |
425 | 425 |
|
426 | 426 |
|
427 |
LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) {
|
|
428 |
int index = GetNextSpillIndex(is_double);
|
|
429 |
if (is_double) {
|
|
427 |
LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
|
|
428 |
int index = GetNextSpillIndex(kind);
|
|
429 |
if (kind == DOUBLE_REGISTERS) {
|
|
430 | 430 |
return LDoubleStackSlot::Create(index, zone()); |
431 | 431 |
} else { |
432 |
ASSERT(kind == GENERAL_REGISTERS); |
|
432 | 433 |
return LStackSlot::Create(index, zone()); |
433 | 434 |
} |
434 | 435 |
} |
... | ... | |
444 | 445 |
// which will be subsumed into this frame. |
445 | 446 |
if (graph()->has_osr()) { |
446 | 447 |
for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) { |
447 |
chunk_->GetNextSpillIndex(false);
|
|
448 |
chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
|
|
448 | 449 |
} |
449 | 450 |
} |
450 | 451 |
|
... | ... | |
660 | 661 |
|
661 | 662 |
LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { |
662 | 663 |
ASSERT(!instr->HasPointerMap()); |
663 |
instr->set_pointer_map(new(zone()) LPointerMap(position_, zone()));
|
|
664 |
instr->set_pointer_map(new(zone()) LPointerMap(zone())); |
|
664 | 665 |
return instr; |
665 | 666 |
} |
666 | 667 |
|
... | ... | |
715 | 716 |
|
716 | 717 |
LInstruction* LChunkBuilder::DoShift(Token::Value op, |
717 | 718 |
HBitwiseBinaryOperation* instr) { |
718 |
if (instr->representation().IsTagged()) { |
|
719 |
ASSERT(instr->left()->representation().IsTagged()); |
|
720 |
ASSERT(instr->right()->representation().IsTagged()); |
|
721 |
|
|
722 |
LOperand* left = UseFixed(instr->left(), a1); |
|
723 |
LOperand* right = UseFixed(instr->right(), a0); |
|
724 |
LArithmeticT* result = new(zone()) LArithmeticT(op, left, right); |
|
725 |
return MarkAsCall(DefineFixed(result, v0), instr); |
|
726 |
} |
|
727 |
|
|
728 |
ASSERT(instr->representation().IsSmiOrInteger32()); |
|
729 |
ASSERT(instr->left()->representation().Equals(instr->representation())); |
|
730 |
ASSERT(instr->right()->representation().Equals(instr->representation())); |
|
731 |
LOperand* left = UseRegisterAtStart(instr->left()); |
|
719 |
if (instr->representation().IsSmiOrInteger32()) { |
|
720 |
ASSERT(instr->left()->representation().Equals(instr->representation())); |
|
721 |
ASSERT(instr->right()->representation().Equals(instr->representation())); |
|
722 |
LOperand* left = UseRegisterAtStart(instr->left()); |
|
732 | 723 |
|
733 |
HValue* right_value = instr->right(); |
|
734 |
LOperand* right = NULL; |
|
735 |
int constant_value = 0; |
|
736 |
bool does_deopt = false; |
|
737 |
if (right_value->IsConstant()) { |
|
738 |
HConstant* constant = HConstant::cast(right_value); |
|
739 |
right = chunk_->DefineConstantOperand(constant); |
|
740 |
constant_value = constant->Integer32Value() & 0x1f; |
|
741 |
// Left shifts can deoptimize if we shift by > 0 and the result cannot be |
|
742 |
// truncated to smi. |
|
743 |
if (instr->representation().IsSmi() && constant_value > 0) { |
|
744 |
does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi); |
|
724 |
HValue* right_value = instr->right(); |
|
725 |
LOperand* right = NULL; |
|
726 |
int constant_value = 0; |
|
727 |
bool does_deopt = false; |
|
728 |
if (right_value->IsConstant()) { |
|
729 |
HConstant* constant = HConstant::cast(right_value); |
|
730 |
right = chunk_->DefineConstantOperand(constant); |
|
731 |
constant_value = constant->Integer32Value() & 0x1f; |
|
732 |
// Left shifts can deoptimize if we shift by > 0 and the result cannot be |
|
733 |
// truncated to smi. |
|
734 |
if (instr->representation().IsSmi() && constant_value > 0) { |
|
735 |
does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi); |
|
736 |
} |
|
737 |
} else { |
|
738 |
right = UseRegisterAtStart(right_value); |
|
745 | 739 |
} |
746 |
} else { |
|
747 |
right = UseRegisterAtStart(right_value); |
|
748 |
} |
|
749 | 740 |
|
750 |
// Shift operations can deoptimize if we do a logical shift |
|
751 |
// by 0 and the result cannot be truncated to int32. |
|
752 |
if (op == Token::SHR && constant_value == 0) { |
|
753 |
if (FLAG_opt_safe_uint32_operations) { |
|
754 |
does_deopt = !instr->CheckFlag(HInstruction::kUint32); |
|
755 |
} else { |
|
756 |
does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); |
|
741 |
// Shift operations can only deoptimize if we do a logical shift |
|
742 |
// by 0 and the result cannot be truncated to int32. |
|
743 |
if (op == Token::SHR && constant_value == 0) { |
|
744 |
if (FLAG_opt_safe_uint32_operations) { |
|
745 |
does_deopt = !instr->CheckFlag(HInstruction::kUint32); |
|
746 |
} else { |
|
747 |
does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); |
|
748 |
} |
|
757 | 749 |
} |
758 |
} |
|
759 | 750 |
|
760 |
LInstruction* result = |
|
761 |
DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt)); |
|
762 |
return does_deopt ? AssignEnvironment(result) : result; |
|
751 |
LInstruction* result = |
|
752 |
DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt)); |
|
753 |
return does_deopt ? AssignEnvironment(result) : result; |
|
754 |
} else { |
|
755 |
return DoArithmeticT(op, instr); |
|
756 |
} |
|
763 | 757 |
} |
764 | 758 |
|
765 | 759 |
|
... | ... | |
768 | 762 |
ASSERT(instr->representation().IsDouble()); |
769 | 763 |
ASSERT(instr->left()->representation().IsDouble()); |
770 | 764 |
ASSERT(instr->right()->representation().IsDouble()); |
771 |
ASSERT(op != Token::MOD); |
|
772 |
LOperand* left = UseRegisterAtStart(instr->left()); |
|
773 |
LOperand* right = UseRegisterAtStart(instr->right()); |
|
774 |
LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
|
775 |
return DefineAsRegister(result); |
|
765 |
if (op == Token::MOD) { |
|
766 |
LOperand* left = UseFixedDouble(instr->left(), f2); |
|
767 |
LOperand* right = UseFixedDouble(instr->right(), f4); |
|
768 |
LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
|
769 |
// We call a C function for double modulo. It can't trigger a GC. We need |
|
770 |
// to use fixed result register for the call. |
|
771 |
// TODO(fschneider): Allow any register as input registers. |
|
772 |
return MarkAsCall(DefineFixedDouble(result, f2), instr); |
|
773 |
} else { |
|
774 |
LOperand* left = UseRegisterAtStart(instr->left()); |
|
775 |
LOperand* right = UseRegisterAtStart(instr->right()); |
|
776 |
LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
|
777 |
return DefineAsRegister(result); |
|
778 |
} |
|
776 | 779 |
} |
777 | 780 |
|
778 | 781 |
|
779 | 782 |
LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
780 |
HArithmeticBinaryOperation* instr) { |
|
781 |
ASSERT(op == Token::ADD || |
|
782 |
op == Token::DIV || |
|
783 |
op == Token::MOD || |
|
784 |
op == Token::MUL || |
|
785 |
op == Token::SUB); |
|
783 |
HBinaryOperation* instr) { |
|
786 | 784 |
HValue* left = instr->left(); |
787 | 785 |
HValue* right = instr->right(); |
788 | 786 |
ASSERT(left->representation().IsTagged()); |
789 | 787 |
ASSERT(right->representation().IsTagged()); |
788 |
LOperand* context = UseFixed(instr->context(), cp); |
|
790 | 789 |
LOperand* left_operand = UseFixed(left, a1); |
791 | 790 |
LOperand* right_operand = UseFixed(right, a0); |
792 | 791 |
LArithmeticT* result = |
793 |
new(zone()) LArithmeticT(op, left_operand, right_operand); |
|
792 |
new(zone()) LArithmeticT(op, context, left_operand, right_operand);
|
|
794 | 793 |
return MarkAsCall(DefineFixed(result, v0), instr); |
795 | 794 |
} |
796 | 795 |
|
... | ... | |
866 | 865 |
HInstruction* old_current = current_instruction_; |
867 | 866 |
current_instruction_ = current; |
868 | 867 |
if (current->has_position()) position_ = current->position(); |
869 |
LInstruction* instr = current->CompileToLithium(this); |
|
868 |
|
|
869 |
LInstruction* instr = NULL; |
|
870 |
if (current->CanReplaceWithDummyUses()) { |
|
871 |
HValue* first_operand = current->OperandCount() == 0 |
|
872 |
? graph()->GetConstant1() |
|
873 |
: current->OperandAt(0); |
|
874 |
instr = DefineAsRegister(new(zone()) LDummyUse(UseAny(first_operand))); |
|
875 |
for (int i = 1; i < current->OperandCount(); ++i) { |
|
876 |
LInstruction* dummy = |
|
877 |
new(zone()) LDummyUse(UseAny(current->OperandAt(i))); |
|
878 |
dummy->set_hydrogen_value(current); |
|
879 |
chunk_->AddInstruction(dummy, current_block_); |
|
880 |
} |
|
881 |
} else { |
|
882 |
instr = current->CompileToLithium(this); |
|
883 |
} |
|
884 |
|
|
885 |
argument_count_ += current->argument_delta(); |
|
886 |
ASSERT(argument_count_ >= 0); |
|
870 | 887 |
|
871 | 888 |
if (instr != NULL) { |
889 |
// Associate the hydrogen instruction first, since we may need it for |
|
890 |
// the ClobbersRegisters() or ClobbersDoubleRegisters() calls below. |
|
891 |
instr->set_hydrogen_value(current); |
|
892 |
|
|
872 | 893 |
#if DEBUG |
873 | 894 |
// Make sure that the lithium instruction has either no fixed register |
874 | 895 |
// constraints in temps or the result OR no uses that are only used at |
... | ... | |
898 | 919 |
} |
899 | 920 |
#endif |
900 | 921 |
|
901 |
instr->set_position(position_); |
|
902 | 922 |
if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
903 | 923 |
instr = AssignPointerMap(instr); |
904 | 924 |
} |
905 | 925 |
if (FLAG_stress_environments && !instr->HasEnvironment()) { |
906 | 926 |
instr = AssignEnvironment(instr); |
907 | 927 |
} |
908 |
instr->set_hydrogen_value(current); |
|
909 | 928 |
chunk_->AddInstruction(instr, current_block_); |
910 | 929 |
} |
911 | 930 |
current_instruction_ = old_current; |
... | ... | |
997 | 1016 |
|
998 | 1017 |
|
999 | 1018 |
LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
1000 |
return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
|
|
1019 |
return new(zone()) LGoto(instr->FirstSuccessor()); |
|
1001 | 1020 |
} |
1002 | 1021 |
|
1003 | 1022 |
|
1004 | 1023 |
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
1005 |
HValue* value = instr->value(); |
|
1006 |
if (value->EmitAtUses()) { |
|
1007 |
HBasicBlock* successor = HConstant::cast(value)->BooleanValue() |
|
1008 |
? instr->FirstSuccessor() |
|
1009 |
: instr->SecondSuccessor(); |
|
1010 |
return new(zone()) LGoto(successor->block_id()); |
|
1011 |
} |
|
1024 |
LInstruction* goto_instr = CheckElideControlInstruction(instr); |
|
1025 |
if (goto_instr != NULL) return goto_instr; |
|
1012 | 1026 |
|
1027 |
HValue* value = instr->value(); |
|
1013 | 1028 |
LBranch* result = new(zone()) LBranch(UseRegister(value)); |
1014 | 1029 |
// Tagged values that are not known smis or booleans require a |
1015 | 1030 |
// deoptimization environment. If the instruction is generic no |
... | ... | |
1047 | 1062 |
|
1048 | 1063 |
|
1049 | 1064 |
LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { |
1065 |
LOperand* context = UseFixed(instr->context(), cp); |
|
1050 | 1066 |
LInstanceOf* result = |
1051 |
new(zone()) LInstanceOf(UseFixed(instr->left(), a0), |
|
1067 |
new(zone()) LInstanceOf(context, UseFixed(instr->left(), a0),
|
|
1052 | 1068 |
UseFixed(instr->right(), a1)); |
1053 | 1069 |
return MarkAsCall(DefineFixed(result, v0), instr); |
1054 | 1070 |
} |
... | ... | |
1057 | 1073 |
LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( |
1058 | 1074 |
HInstanceOfKnownGlobal* instr) { |
1059 | 1075 |
LInstanceOfKnownGlobal* result = |
1060 |
new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), a0), |
|
1061 |
FixedTemp(t0)); |
|
1076 |
new(zone()) LInstanceOfKnownGlobal( |
|
1077 |
UseFixed(instr->context(), cp), |
|
1078 |
UseFixed(instr->left(), a0), |
|
1079 |
FixedTemp(t0)); |
|
1062 | 1080 |
return MarkAsCall(DefineFixed(result, v0), instr); |
1063 | 1081 |
} |
1064 | 1082 |
|
1065 | 1083 |
|
1066 |
LInstruction* LChunkBuilder::DoInstanceSize(HInstanceSize* instr) { |
|
1067 |
LOperand* object = UseRegisterAtStart(instr->object()); |
|
1068 |
return DefineAsRegister(new(zone()) LInstanceSize(object)); |
|
1069 |
} |
|
1070 |
|
|
1071 |
|
|
1072 | 1084 |
LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { |
1073 | 1085 |
LOperand* receiver = UseRegisterAtStart(instr->receiver()); |
1074 | 1086 |
LOperand* function = UseRegisterAtStart(instr->function()); |
... | ... | |
1091 | 1103 |
|
1092 | 1104 |
|
1093 | 1105 |
LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { |
1094 |
++argument_count_; |
|
1095 | 1106 |
LOperand* argument = Use(instr->argument()); |
1096 | 1107 |
return new(zone()) LPushArgument(argument); |
1097 | 1108 |
} |
... | ... | |
1122 | 1133 |
|
1123 | 1134 |
|
1124 | 1135 |
LInstruction* LChunkBuilder::DoContext(HContext* instr) { |
1125 |
// If there is a non-return use, the context must be allocated in a register. |
|
1126 |
for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { |
|
1127 |
if (!it.value()->IsReturn()) { |
|
1128 |
return DefineAsRegister(new(zone()) LContext); |
|
1129 |
} |
|
1136 |
if (instr->HasNoUses()) return NULL; |
|
1137 |
|
|
1138 |
if (info()->IsStub()) { |
|
1139 |
return DefineFixed(new(zone()) LContext, cp); |
|
1130 | 1140 |
} |
1131 | 1141 |
|
1132 |
return NULL;
|
|
1142 |
return DefineAsRegister(new(zone()) LContext);
|
|
1133 | 1143 |
} |
1134 | 1144 |
|
1135 | 1145 |
|
... | ... | |
1140 | 1150 |
|
1141 | 1151 |
|
1142 | 1152 |
LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) { |
1143 |
return MarkAsCall(new(zone()) LDeclareGlobals, instr); |
|
1153 |
LOperand* context = UseFixed(instr->context(), cp); |
|
1154 |
return MarkAsCall(new(zone()) LDeclareGlobals(context), instr); |
|
1144 | 1155 |
} |
1145 | 1156 |
|
1146 | 1157 |
|
... | ... | |
1158 | 1169 |
|
1159 | 1170 |
LInstruction* LChunkBuilder::DoCallConstantFunction( |
1160 | 1171 |
HCallConstantFunction* instr) { |
1161 |
argument_count_ -= instr->argument_count(); |
|
1162 | 1172 |
return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, v0), instr); |
1163 | 1173 |
} |
1164 | 1174 |
|
1165 | 1175 |
|
1166 | 1176 |
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) { |
1177 |
LOperand* context = UseFixed(instr->context(), cp); |
|
1167 | 1178 |
LOperand* function = UseFixed(instr->function(), a1); |
1168 |
argument_count_ -= instr->argument_count(); |
|
1169 |
LInvokeFunction* result = new(zone()) LInvokeFunction(function); |
|
1179 |
LInvokeFunction* result = new(zone()) LInvokeFunction(context, function); |
|
1170 | 1180 |
return MarkAsCall(DefineFixed(result, v0), instr, CANNOT_DEOPTIMIZE_EAGERLY); |
1171 | 1181 |
} |
1172 | 1182 |
|
... | ... | |
1221 | 1231 |
LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) { |
1222 | 1232 |
ASSERT(instr->representation().IsDouble()); |
1223 | 1233 |
ASSERT(instr->value()->representation().IsDouble()); |
1224 |
LOperand* input = UseTempRegister(instr->value());
|
|
1234 |
LOperand* input = UseRegister(instr->value()); |
|
1225 | 1235 |
LOperand* temp1 = TempRegister(); |
1226 | 1236 |
LOperand* temp2 = TempRegister(); |
1227 | 1237 |
LOperand* double_temp = FixedTemp(f6); // Chosen by fair dice roll. |
... | ... | |
1240 | 1250 |
|
1241 | 1251 |
|
1242 | 1252 |
LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { |
1253 |
Representation r = instr->value()->representation(); |
|
1254 |
LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32()) |
|
1255 |
? NULL |
|
1256 |
: UseFixed(instr->context(), cp); |
|
1243 | 1257 |
LOperand* input = UseRegister(instr->value()); |
1244 |
LMathAbs* result = new(zone()) LMathAbs(input); |
|
1258 |
LMathAbs* result = new(zone()) LMathAbs(context, input);
|
|
1245 | 1259 |
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
1246 | 1260 |
} |
1247 | 1261 |
|
... | ... | |
1271 | 1285 |
|
1272 | 1286 |
LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { |
1273 | 1287 |
ASSERT(instr->key()->representation().IsTagged()); |
1274 |
argument_count_ -= instr->argument_count();
|
|
1288 |
LOperand* context = UseFixed(instr->context(), cp);
|
|
1275 | 1289 |
LOperand* key = UseFixed(instr->key(), a2); |
1276 |
return MarkAsCall(DefineFixed(new(zone()) LCallKeyed(key), v0), instr); |
|
1290 |
return MarkAsCall( |
|
1291 |
DefineFixed(new(zone()) LCallKeyed(context, key), v0), instr); |
|
1277 | 1292 |
} |
1278 | 1293 |
|
1279 | 1294 |
|
1280 | 1295 |
LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { |
1281 |
argument_count_ -= instr->argument_count();
|
|
1282 |
return MarkAsCall(DefineFixed(new(zone()) LCallNamed, v0), instr); |
|
1296 |
LOperand* context = UseFixed(instr->context(), cp);
|
|
1297 |
return MarkAsCall(DefineFixed(new(zone()) LCallNamed(context), v0), instr);
|
|
1283 | 1298 |
} |
1284 | 1299 |
|
1285 | 1300 |
|
1286 | 1301 |
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { |
1287 |
argument_count_ -= instr->argument_count();
|
|
1288 |
return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, v0), instr); |
|
1302 |
LOperand* context = UseFixed(instr->context(), cp);
|
|
1303 |
return MarkAsCall(DefineFixed(new(zone()) LCallGlobal(context), v0), instr);
|
|
1289 | 1304 |
} |
1290 | 1305 |
|
1291 | 1306 |
|
1292 | 1307 |
LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { |
1293 |
argument_count_ -= instr->argument_count(); |
|
1294 | 1308 |
return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, v0), instr); |
1295 | 1309 |
} |
1296 | 1310 |
|
1297 | 1311 |
|
1298 | 1312 |
LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { |
1313 |
LOperand* context = UseFixed(instr->context(), cp); |
|
1299 | 1314 |
LOperand* constructor = UseFixed(instr->constructor(), a1); |
1300 |
argument_count_ -= instr->argument_count(); |
|
1301 |
LCallNew* result = new(zone()) LCallNew(constructor); |
|
1315 |
LCallNew* result = new(zone()) LCallNew(context, constructor); |
|
1302 | 1316 |
return MarkAsCall(DefineFixed(result, v0), instr); |
1303 | 1317 |
} |
1304 | 1318 |
|
1305 | 1319 |
|
1306 | 1320 |
LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) { |
1321 |
LOperand* context = UseFixed(instr->context(), cp); |
|
1307 | 1322 |
LOperand* constructor = UseFixed(instr->constructor(), a1); |
1308 |
argument_count_ -= instr->argument_count(); |
|
1309 |
LCallNewArray* result = new(zone()) LCallNewArray(constructor); |
|
1323 |
LCallNewArray* result = new(zone()) LCallNewArray(context, constructor); |
|
1310 | 1324 |
return MarkAsCall(DefineFixed(result, v0), instr); |
1311 | 1325 |
} |
1312 | 1326 |
|
1313 | 1327 |
|
1314 | 1328 |
LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { |
1329 |
LOperand* context = UseFixed(instr->context(), cp); |
|
1315 | 1330 |
LOperand* function = UseFixed(instr->function(), a1); |
1316 |
argument_count_ -= instr->argument_count(); |
|
1317 |
return MarkAsCall(DefineFixed(new(zone()) LCallFunction(function), v0), |
|
1318 |
instr); |
|
1331 |
return MarkAsCall( |
|
1332 |
DefineFixed(new(zone()) LCallFunction(context, function), v0), instr); |
|
1319 | 1333 |
} |
1320 | 1334 |
|
1321 | 1335 |
|
1322 | 1336 |
LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { |
1323 |
argument_count_ -= instr->argument_count();
|
|
1324 |
return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, v0), instr); |
|
1337 |
LOperand* context = UseFixed(instr->context(), cp);
|
|
1338 |
return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), v0), instr);
|
|
1325 | 1339 |
} |
1326 | 1340 |
|
1327 | 1341 |
|
... | ... | |
1349 | 1363 |
if (instr->representation().IsSmiOrInteger32()) { |
1350 | 1364 |
ASSERT(instr->left()->representation().Equals(instr->representation())); |
1351 | 1365 |
ASSERT(instr->right()->representation().Equals(instr->representation())); |
1366 |
ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32)); |
|
1352 | 1367 |
|
1353 | 1368 |
LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1354 | 1369 |
LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
1355 | 1370 |
return DefineAsRegister(new(zone()) LBitI(left, right)); |
1356 | 1371 |
} else { |
1357 |
ASSERT(instr->representation().IsTagged()); |
|
1358 |
ASSERT(instr->left()->representation().IsTagged()); |
|
1359 |
ASSERT(instr->right()->representation().IsTagged()); |
|
1360 |
|
|
1361 |
LOperand* left = UseFixed(instr->left(), a1); |
|
1362 |
LOperand* right = UseFixed(instr->right(), a0); |
|
1363 |
LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right); |
|
1364 |
return MarkAsCall(DefineFixed(result, v0), instr); |
|
1372 |
return DoArithmeticT(instr->op(), instr); |
|
1365 | 1373 |
} |
1366 | 1374 |
} |
1367 | 1375 |
|
1368 | 1376 |
|
1369 | 1377 |
LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
1370 |
if (instr->representation().IsDouble()) { |
|
1371 |
return DoArithmeticD(Token::DIV, instr); |
|
1372 |
} else if (instr->representation().IsSmiOrInteger32()) { |
|
1378 |
if (instr->representation().IsSmiOrInteger32()) { |
|
1373 | 1379 |
ASSERT(instr->left()->representation().Equals(instr->representation())); |
1374 | 1380 |
ASSERT(instr->right()->representation().Equals(instr->representation())); |
1375 | 1381 |
LOperand* dividend = UseRegister(instr->left()); |
1376 | 1382 |
LOperand* divisor = UseRegister(instr->right()); |
1377 | 1383 |
LDivI* div = new(zone()) LDivI(dividend, divisor); |
1378 | 1384 |
return AssignEnvironment(DefineAsRegister(div)); |
1385 |
} else if (instr->representation().IsDouble()) { |
|
1386 |
return DoArithmeticD(Token::DIV, instr); |
|
1379 | 1387 |
} else { |
1380 | 1388 |
return DoArithmeticT(Token::DIV, instr); |
1381 | 1389 |
} |
... | ... | |
1466 | 1474 |
? AssignEnvironment(result) |
1467 | 1475 |
: result; |
1468 | 1476 |
} |
1469 |
} else if (instr->representation().IsTagged()) {
|
|
1470 |
return DoArithmeticT(Token::MOD, instr);
|
|
1477 |
} else if (instr->representation().IsDouble()) {
|
|
1478 |
return DoArithmeticD(Token::MOD, instr);
|
|
1471 | 1479 |
} else { |
1472 |
ASSERT(instr->representation().IsDouble()); |
|
1473 |
// We call a C function for double modulo. It can't trigger a GC. We need |
|
1474 |
// to use fixed result register for the call. |
|
1475 |
// TODO(fschneider): Allow any register as input registers. |
|
1476 |
LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, |
|
1477 |
UseFixedDouble(left, f2), |
|
1478 |
UseFixedDouble(right, f4)); |
|
1479 |
return MarkAsCall(DefineFixedDouble(mod, f2), instr); |
|
1480 |
return DoArithmeticT(Token::MOD, instr); |
|
1480 | 1481 |
} |
1481 | 1482 |
} |
1482 | 1483 |
|
... | ... | |
1485 | 1486 |
if (instr->representation().IsSmiOrInteger32()) { |
1486 | 1487 |
ASSERT(instr->left()->representation().Equals(instr->representation())); |
1487 | 1488 |
ASSERT(instr->right()->representation().Equals(instr->representation())); |
1488 |
LOperand* left; |
|
1489 |
LOperand* right = UseOrConstant(instr->BetterRightOperand()); |
|
1490 |
LOperand* temp = NULL; |
|
1491 |
if (instr->CheckFlag(HValue::kBailoutOnMinusZero) && |
|
1492 |
(instr->CheckFlag(HValue::kCanOverflow) || |
|
1493 |
!right->IsConstantOperand())) { |
|
1494 |
left = UseRegister(instr->BetterLeftOperand()); |
|
1495 |
temp = TempRegister(); |
|
1489 |
HValue* left = instr->BetterLeftOperand(); |
|
1490 |
HValue* right = instr->BetterRightOperand(); |
|
1491 |
LOperand* left_op; |
|
1492 |
LOperand* right_op; |
|
1493 |
bool can_overflow = instr->CheckFlag(HValue::kCanOverflow); |
|
1494 |
bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero); |
|
1495 |
|
|
1496 |
if (right->IsConstant()) { |
|
1497 |
HConstant* constant = HConstant::cast(right); |
|
1498 |
int32_t constant_value = constant->Integer32Value(); |
|
1499 |
// Constants -1, 0 and 1 can be optimized if the result can overflow. |
|
1500 |
// For other constants, it can be optimized only without overflow. |
|
1501 |
if (!can_overflow || ((constant_value >= -1) && (constant_value <= 1))) { |
|
1502 |
left_op = UseRegisterAtStart(left); |
|
1503 |
right_op = UseConstant(right); |
|
1504 |
} else { |
|
1505 |
if (bailout_on_minus_zero) { |
|
1506 |
left_op = UseRegister(left); |
|
1507 |
} else { |
|
1508 |
left_op = UseRegisterAtStart(left); |
|
1509 |
} |
|
1510 |
right_op = UseRegister(right); |
|
1511 |
} |
|
1496 | 1512 |
} else { |
1497 |
left = UseRegisterAtStart(instr->BetterLeftOperand()); |
|
1513 |
if (bailout_on_minus_zero) { |
|
1514 |
left_op = UseRegister(left); |
|
1515 |
} else { |
|
1516 |
left_op = UseRegisterAtStart(left); |
|
1517 |
} |
|
1518 |
right_op = UseRegister(right); |
|
1498 | 1519 |
} |
1499 |
LMulI* mul = new(zone()) LMulI(left, right, temp); |
|
1500 |
if (instr->CheckFlag(HValue::kCanOverflow) || |
|
1501 |
instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
|
1520 |
LMulI* mul = new(zone()) LMulI(left_op, right_op); |
|
1521 |
if (can_overflow || bailout_on_minus_zero) { |
|
1502 | 1522 |
AssignEnvironment(mul); |
1503 | 1523 |
} |
1504 | 1524 |
return DefineAsRegister(mul); |
... | ... | |
1579 | 1599 |
} |
1580 | 1600 |
return DoArithmeticD(Token::ADD, instr); |
1581 | 1601 |
} else { |
1582 |
ASSERT(instr->representation().IsTagged()); |
|
1583 | 1602 |
return DoArithmeticT(Token::ADD, instr); |
1584 | 1603 |
} |
1585 | 1604 |
} |
... | ... | |
1637 | 1656 |
LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { |
1638 | 1657 |
ASSERT(instr->left()->representation().IsTagged()); |
1639 | 1658 |
ASSERT(instr->right()->representation().IsTagged()); |
1659 |
LOperand* context = UseFixed(instr->context(), cp); |
|
1640 | 1660 |
LOperand* left = UseFixed(instr->left(), a1); |
1641 | 1661 |
LOperand* right = UseFixed(instr->right(), a0); |
1642 |
LCmpT* result = new(zone()) LCmpT(left, right); |
|
1662 |
LCmpT* result = new(zone()) LCmpT(context, left, right);
|
|
1643 | 1663 |
return MarkAsCall(DefineFixed(result, v0), instr); |
1644 | 1664 |
} |
1645 | 1665 |
|
... | ... | |
1666 | 1686 |
|
1667 | 1687 |
LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( |
1668 | 1688 |
HCompareObjectEqAndBranch* instr) { |
1689 |
LInstruction* goto_instr = CheckElideControlInstruction(instr); |
|
1690 |
if (goto_instr != NULL) return goto_instr; |
|
1669 | 1691 |
LOperand* left = UseRegisterAtStart(instr->left()); |
1670 | 1692 |
LOperand* right = UseRegisterAtStart(instr->right()); |
1671 | 1693 |
return new(zone()) LCmpObjectEqAndBranch(left, right); |
... | ... | |
1674 | 1696 |
|
1675 | 1697 |
LInstruction* LChunkBuilder::DoCompareHoleAndBranch( |
1676 | 1698 |
HCompareHoleAndBranch* instr) { |
1677 |
LOperand* object = UseRegisterAtStart(instr->object());
|
|
1678 |
return new(zone()) LCmpHoleAndBranch(object);
|
|
1699 |
LOperand* value = UseRegisterAtStart(instr->value());
|
|
1700 |
return new(zone()) LCmpHoleAndBranch(value);
|
|
1679 | 1701 |
} |
1680 | 1702 |
|
1681 | 1703 |
|
... | ... | |
1713 | 1735 |
HStringCompareAndBranch* instr) { |
1714 | 1736 |
ASSERT(instr->left()->representation().IsTagged()); |
1715 | 1737 |
ASSERT(instr->right()->representation().IsTagged()); |
1738 |
LOperand* context = UseFixed(instr->context(), cp); |
|
1716 | 1739 |
LOperand* left = UseFixed(instr->left(), a1); |
1717 | 1740 |
LOperand* right = UseFixed(instr->right(), a0); |
1718 | 1741 |
LStringCompareAndBranch* result = |
1719 |
new(zone()) LStringCompareAndBranch(left, right); |
|
1742 |
new(zone()) LStringCompareAndBranch(context, left, right);
|
|
1720 | 1743 |
return MarkAsCall(result, instr); |
1721 | 1744 |
} |
1722 | 1745 |
|
... | ... | |
1783 | 1806 |
|
1784 | 1807 |
LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { |
1785 | 1808 |
LOperand* string = UseRegister(instr->string()); |
1786 |
LOperand* index = UseRegister(instr->index()); |
|
1787 |
LOperand* value = UseTempRegister(instr->value()); |
|
1788 |
LSeqStringSetChar* result = |
|
1789 |
new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value); |
|
1790 |
return DefineAsRegister(result); |
|
1809 |
LOperand* index = UseRegisterOrConstant(instr->index()); |
|
1810 |
LOperand* value = UseRegister(instr->value()); |
|
1811 |
return new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value); |
|
1791 | 1812 |
} |
1792 | 1813 |
|
1793 | 1814 |
|
... | ... | |
1805 | 1826 |
} |
1806 | 1827 |
|
1807 | 1828 |
|
1829 |
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { |
|
1830 |
// The control instruction marking the end of a block that completed |
|
1831 |
// abruptly (e.g., threw an exception). There is nothing specific to do. |
|
1832 |
return NULL; |
|
1833 |
} |
|
1834 |
|
|
1835 |
|
|
1808 | 1836 |
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { |
1837 |
LOperand* context = UseFixed(instr->context(), cp); |
|
1809 | 1838 |
LOperand* value = UseFixed(instr->value(), a0); |
1810 |
return MarkAsCall(new(zone()) LThrow(value), instr); |
|
1839 |
return MarkAsCall(new(zone()) LThrow(context, value), instr);
|
|
1811 | 1840 |
} |
1812 | 1841 |
|
1813 | 1842 |
|
... | ... | |
1836 | 1865 |
} |
1837 | 1866 |
if (from.IsTagged()) { |
1838 | 1867 |
if (to.IsDouble()) { |
1839 |
info()->MarkAsDeferredCalling(); |
|
1840 | 1868 |
LOperand* value = UseRegister(instr->value()); |
1841 | 1869 |
LNumberUntagD* res = new(zone()) LNumberUntagD(value); |
1842 | 1870 |
return AssignEnvironment(DefineAsRegister(res)); |
... | ... | |
1940 | 1968 |
} |
1941 | 1969 |
|
1942 | 1970 |
|
1943 |
LInstruction* LChunkBuilder::DoIsNumberAndBranch(HIsNumberAndBranch* instr) { |
|
1944 |
return new(zone()) |
|
1945 |
LIsNumberAndBranch(UseRegisterOrConstantAtStart(instr->value())); |
|
1946 |
} |
|
1947 |
|
|
1948 |
|
|
1949 | 1971 |
LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
1950 | 1972 |
LOperand* value = UseRegisterAtStart(instr->value()); |
1951 | 1973 |
LInstruction* result = new(zone()) LCheckInstanceType(value); |
... | ... | |
1994 | 2016 |
|
1995 | 2017 |
|
1996 | 2018 |
LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { |
2019 |
LOperand* context = info()->IsStub() |
|
2020 |
? UseFixed(instr->context(), cp) |
|
2021 |
: NULL; |
|
1997 | 2022 |
LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count()); |
1998 |
return new(zone()) LReturn(UseFixed(instr->value(), v0), |
|
2023 |
return new(zone()) LReturn(UseFixed(instr->value(), v0), context,
|
|
1999 | 2024 |
parameter_count); |
2000 | 2025 |
} |
2001 | 2026 |
|
... | ... | |
2028 | 2053 |
|
2029 | 2054 |
|
2030 | 2055 |
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { |
2056 |
LOperand* context = UseFixed(instr->context(), cp); |
|
2031 | 2057 |
LOperand* global_object = UseFixed(instr->global_object(), a0); |
2032 |
LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object); |
|
2058 |
LLoadGlobalGeneric* result = |
|
2059 |
new(zone()) LLoadGlobalGeneric(context, global_object); |
|
2033 | 2060 |
return MarkAsCall(DefineFixed(result, v0), instr); |
2034 | 2061 |
} |
2035 | 2062 |
|
... | ... | |
2045 | 2072 |
|
2046 | 2073 |
|
2047 | 2074 |
LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) { |
2075 |
LOperand* context = UseFixed(instr->context(), cp); |
|
2048 | 2076 |
LOperand* global_object = UseFixed(instr->global_object(), a1); |
2049 | 2077 |
LOperand* value = UseFixed(instr->value(), a0); |
2050 | 2078 |
LStoreGlobalGeneric* result = |
2051 |
new(zone()) LStoreGlobalGeneric(global_object, value); |
|
2079 |
new(zone()) LStoreGlobalGeneric(context, global_object, value);
|
|
2052 | 2080 |
return MarkAsCall(result, instr); |
2053 | 2081 |
} |
2054 | 2082 |
|
... | ... | |
2083 | 2111 |
|
2084 | 2112 |
|
2085 | 2113 |
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { |
2114 |
LOperand* context = UseFixed(instr->context(), cp); |
|
2086 | 2115 |
LOperand* object = UseFixed(instr->object(), a0); |
2087 |
LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), v0); |
|
2116 |
LInstruction* result = |
|
2117 |
DefineFixed(new(zone()) LLoadNamedGeneric(context, object), v0); |
|
2088 | 2118 |
return MarkAsCall(result, instr); |
2089 | 2119 |
} |
2090 | 2120 |
|
... | ... | |
2096 | 2126 |
} |
2097 | 2127 |
|
2098 | 2128 |
|
2129 |
LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { |
|
2130 |
return DefineAsRegister(new(zone()) LLoadRoot); |
|
2131 |
} |
|
2132 |
|
|
2133 |
|
|
2099 | 2134 |
LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( |
2100 | 2135 |
HLoadExternalArrayPointer* instr) { |
2101 | 2136 |
LOperand* input = UseRegisterAtStart(instr->value()); |
... | ... | |
2112 | 2147 |
if (!instr->is_external()) { |
2113 | 2148 |
LOperand* obj = NULL; |
2114 | 2149 |
if (instr->representation().IsDouble()) { |
2115 |
obj = UseTempRegister(instr->elements());
|
|
2150 |
obj = UseRegister(instr->elements()); |
|
2116 | 2151 |
} else { |
2117 | 2152 |
ASSERT(instr->representation().IsSmiOrTagged()); |
2118 | 2153 |
obj = UseRegisterAtStart(instr->elements()); |
... | ... | |
2140 | 2175 |
|
2141 | 2176 |
|
2142 | 2177 |
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
2178 |
LOperand* context = UseFixed(instr->context(), cp); |
|
2143 | 2179 |
LOperand* object = UseFixed(instr->object(), a1); |
2144 | 2180 |
LOperand* key = UseFixed(instr->key(), a0); |
2145 | 2181 |
|
2146 | 2182 |
LInstruction* result = |
2147 |
DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), v0); |
|
2183 |
DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), v0);
|
|
2148 | 2184 |
return MarkAsCall(result, instr); |
2149 | 2185 |
} |
2150 | 2186 |
|
2151 | 2187 |
|
2152 | 2188 |
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { |
2153 |
ElementsKind elements_kind = instr->elements_kind(); |
|
2154 |
|
|
2155 | 2189 |
if (!instr->is_external()) { |
2156 | 2190 |
ASSERT(instr->elements()->representation().IsTagged()); |
2157 | 2191 |
bool needs_write_barrier = instr->NeedsWriteBarrier(); |
... | ... | |
2162 | 2196 |
if (instr->value()->representation().IsDouble()) { |
2163 | 2197 |
object = UseRegisterAtStart(instr->elements()); |
2164 | 2198 |
key = UseRegisterOrConstantAtStart(instr->key()); |
2165 |
val = UseTempRegister(instr->value());
|
|
2199 |
val = UseRegister(instr->value()); |
|
2166 | 2200 |
} else { |
2167 | 2201 |
ASSERT(instr->value()->representation().IsSmiOrTagged()); |
2168 |
object = UseTempRegister(instr->elements()); |
|
2169 |
val = needs_write_barrier ? UseTempRegister(instr->value()) |
|
2170 |
: UseRegisterAtStart(instr->value()); |
|
2171 |
key = needs_write_barrier ? UseTempRegister(instr->key()) |
|
2172 |
: UseRegisterOrConstantAtStart(instr->key()); |
|
2202 |
if (needs_write_barrier) { |
|
2203 |
object = UseTempRegister(instr->elements()); |
|
2204 |
val = UseTempRegister(instr->value()); |
|
2205 |
key = UseTempRegister(instr->key()); |
|
2206 |
} else { |
|
2207 |
object = UseRegisterAtStart(instr->elements()); |
|
2208 |
val = UseRegisterAtStart(instr->value()); |
|
2209 |
key = UseRegisterOrConstantAtStart(instr->key()); |
|
2210 |
} |
|
2173 | 2211 |
} |
2174 | 2212 |
|
2175 | 2213 |
return new(zone()) LStoreKeyed(object, key, val); |
... | ... | |
2177 | 2215 |
|
2178 | 2216 |
ASSERT( |
2179 | 2217 |
(instr->value()->representation().IsInteger32() && |
2180 |
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
|
|
2181 |
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
|
|
2218 |
(instr->elements_kind() != EXTERNAL_FLOAT_ELEMENTS) &&
|
|
2219 |
(instr->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS)) ||
|
|
2182 | 2220 |
(instr->value()->representation().IsDouble() && |
2183 |
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
|
|
2184 |
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
|
|
2221 |
((instr->elements_kind() == EXTERNAL_FLOAT_ELEMENTS) ||
|
|
2222 |
(instr->elements_kind() == EXTERNAL_DOUBLE_ELEMENTS))));
|
|
2185 | 2223 |
ASSERT(instr->elements()->representation().IsExternal()); |
2186 |
bool val_is_temp_register = |
|
2187 |
elements_kind == EXTERNAL_PIXEL_ELEMENTS || |
|
2188 |
elements_kind == EXTERNAL_FLOAT_ELEMENTS; |
|
2189 |
LOperand* val = val_is_temp_register ? UseTempRegister(instr->value()) |
|
2190 |
: UseRegister(instr->value()); |
|
2224 |
LOperand* val = UseRegister(instr->value()); |
|
2191 | 2225 |
LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
2192 | 2226 |
LOperand* external_pointer = UseRegister(instr->elements()); |
2193 | 2227 |
|
... | ... | |
2196 | 2230 |
|
2197 | 2231 |
|
2198 | 2232 |
LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { |
2233 |
LOperand* context = UseFixed(instr->context(), cp); |
|
2199 | 2234 |
LOperand* obj = UseFixed(instr->object(), a2); |
2200 | 2235 |
LOperand* key = UseFixed(instr->key(), a1); |
2201 | 2236 |
LOperand* val = UseFixed(instr->value(), a0); |
... | ... | |
2204 | 2239 |
ASSERT(instr->key()->representation().IsTagged()); |
2205 | 2240 |
ASSERT(instr->value()->representation().IsTagged()); |
2206 | 2241 |
|
2207 |
return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr); |
|
2242 |
return MarkAsCall( |
|
2243 |
new(zone()) LStoreKeyedGeneric(context, obj, key, val), instr); |
|
2208 | 2244 |
} |
2209 | 2245 |
|
2210 | 2246 |
|
... | ... | |
2214 | 2250 |
if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { |
2215 | 2251 |
LOperand* new_map_reg = TempRegister(); |
2216 | 2252 |
LTransitionElementsKind* result = |
2217 |
new(zone()) LTransitionElementsKind(object, new_map_reg); |
|
2253 |
new(zone()) LTransitionElementsKind(object, NULL, new_map_reg);
|
|
2218 | 2254 |
return result; |
2219 | 2255 |
} else { |
2256 |
LOperand* context = UseFixed(instr->context(), cp); |
|
2220 | 2257 |
LTransitionElementsKind* result = |
2221 |
new(zone()) LTransitionElementsKind(object, NULL); |
|
2258 |
new(zone()) LTransitionElementsKind(object, context, NULL);
|
|
2222 | 2259 |
return AssignPointerMap(result); |
2223 | 2260 |
} |
2224 | 2261 |
} |
... | ... | |
2277 | 2314 |
|
2278 | 2315 |
|
2279 | 2316 |
LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { |
2317 |
LOperand* context = UseFixed(instr->context(), cp); |
|
2280 | 2318 |
LOperand* obj = UseFixed(instr->object(), a1); |
2281 | 2319 |
LOperand* val = UseFixed(instr->value(), a0); |
2282 | 2320 |
|
2283 |
LInstruction* result = new(zone()) LStoreNamedGeneric(obj, val); |
|
2321 |
LInstruction* result = new(zone()) LStoreNamedGeneric(context, obj, val);
|
|
2284 | 2322 |
return MarkAsCall(result, instr); |
2285 | 2323 |
} |
2286 | 2324 |
|
2287 | 2325 |
|
2288 | 2326 |
LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) { |
2327 |
LOperand* context = UseFixed(instr->context(), cp); |
|
2289 | 2328 |
LOperand* left = UseRegisterAtStart(instr->left()); |
2290 | 2329 |
LOperand* right = UseRegisterAtStart(instr->right()); |
2291 |
return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), v0), |
|
2292 |
instr); |
|
2330 |
return MarkAsCall( |
|
2331 |
DefineFixed(new(zone()) LStringAdd(context, left, right), v0), |
|
2332 |
instr); |
|
2293 | 2333 |
} |
2294 | 2334 |
|
2295 | 2335 |
|
2296 | 2336 |
LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { |
2297 | 2337 |
LOperand* string = UseTempRegister(instr->string()); |
2298 | 2338 |
LOperand* index = UseTempRegister(instr->index()); |
2299 |
LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index); |
|
2339 |
LOperand* context = UseAny(instr->context()); |
|
2340 |
LStringCharCodeAt* result = |
|
2341 |
new(zone()) LStringCharCodeAt(context, string, index); |
|
2300 | 2342 |
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
2301 | 2343 |
} |
2302 | 2344 |
|
2303 | 2345 |
|
2304 | 2346 |
LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { |
2305 | 2347 |
LOperand* char_code = UseRegister(instr->value()); |
2306 |
LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code); |
|
2348 |
LOperand* context = UseAny(instr->context()); |
|
2349 |
LStringCharFromCode* result = |
|
2350 |
new(zone()) LStringCharFromCode(context, char_code); |
|
2307 | 2351 |
return AssignPointerMap(DefineAsRegister(result)); |
2308 | 2352 |
} |
2309 | 2353 |
|
2310 | 2354 |
|
2311 | 2355 |
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { |
2312 | 2356 |
info()->MarkAsDeferredCalling(); |
2357 |
LOperand* context = UseAny(instr->context()); |
|
2313 | 2358 |
LOperand* size = instr->size()->IsConstant() |
2314 | 2359 |
? UseConstant(instr->size()) |
2315 | 2360 |
: UseTempRegister(instr->size()); |
2316 | 2361 |
LOperand* temp1 = TempRegister(); |
2317 | 2362 |
LOperand* temp2 = TempRegister(); |
2318 |
LAllocate* result = new(zone()) LAllocate(size, temp1, temp2); |
|
2363 |
LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2);
|
|
2319 | 2364 |
return AssignPointerMap(DefineAsRegister(result)); |
2320 | 2365 |
} |
2321 | 2366 |
|
2322 | 2367 |
|
2323 | 2368 |
LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) { |
2324 |
return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, v0), instr); |
|
2369 |
LOperand* context = UseFixed(instr->context(), cp); |
|
2370 |
return MarkAsCall( |
|
2371 |
DefineFixed(new(zone()) LRegExpLiteral(context), v0), instr); |
|
2325 | 2372 |
} |
2326 | 2373 |
|
2327 | 2374 |
|
2328 | 2375 |
LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { |
2329 |
return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, v0), instr); |
|
2376 |
LOperand* context = UseFixed(instr->context(), cp); |
|
2377 |
return MarkAsCall( |
|
2378 |
DefineFixed(new(zone()) LFunctionLiteral(context), v0), instr); |
|
2330 | 2379 |
} |
2331 | 2380 |
|
2332 | 2381 |
|
... | ... | |
2373 | 2422 |
|
2374 | 2423 |
|
2375 | 2424 |
LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { |
2376 |
argument_count_ -= instr->argument_count();
|
|
2377 |
return MarkAsCall(DefineFixed(new(zone()) LCallStub, v0), instr); |
|
2425 |
LOperand* context = UseFixed(instr->context(), cp);
|
|
2426 |
return MarkAsCall(DefineFixed(new(zone()) LCallStub(context), v0), instr);
|
|
2378 | 2427 |
} |
2379 | 2428 |
|
2380 | 2429 |
|
... | ... | |
2419 | 2468 |
|
2420 | 2469 |
|
2421 | 2470 |
LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { |
2422 |
LTypeof* result = new(zone()) LTypeof(UseFixed(instr->value(), a0)); |
|
2471 |
LOperand* context = UseFixed(instr->context(), cp); |
|
2472 |
LTypeof* result = new(zone()) LTypeof(context, UseFixed(instr->value(), a0)); |
|
2423 | 2473 |
return MarkAsCall(DefineFixed(result, v0), instr); |
2424 | 2474 |
} |
2425 | 2475 |
|
... | ... | |
2458 | 2508 |
|
2459 | 2509 |
LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { |
2460 | 2510 |
if (instr->is_function_entry()) { |
2461 |
return MarkAsCall(new(zone()) LStackCheck, instr); |
|
2511 |
LOperand* context = UseFixed(instr->context(), cp); |
|
2512 |
return MarkAsCall(new(zone()) LStackCheck(context), instr); |
|
2462 | 2513 |
} else { |
2463 | 2514 |
ASSERT(instr->is_backwards_branch()); |
2464 |
return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck)); |
|
2515 |
LOperand* context = UseAny(instr->context()); |
|
2516 |
return AssignEnvironment( |
|
2517 |
AssignPointerMap(new(zone()) LStackCheck(context))); |
|
2465 | 2518 |
} |
2466 | 2519 |
} |
2467 | 2520 |
|
... | ... | |
2494 | 2547 |
if (env->entry()->arguments_pushed()) { |
2495 | 2548 |
int argument_count = env->arguments_environment()->parameter_count(); |
2496 | 2549 |
pop = new(zone()) LDrop(argument_count); |
2497 |
argument_count_ -= argument_count;
|
|
2550 |
ASSERT(instr->argument_delta() == -argument_count);
|
|
2498 | 2551 |
} |
2499 | 2552 |
|
2500 | 2553 |
HEnvironment* outer = current_block_->last_environment()-> |
... | ... | |
2506 | 2559 |
|
2507 | 2560 |
|
2508 | 2561 |
LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) { |
2562 |
LOperand* context = UseFixed(instr->context(), cp); |
|
2509 | 2563 |
LOperand* object = UseFixed(instr->enumerable(), a0); |
2510 |
LForInPrepareMap* result = new(zone()) LForInPrepareMap(object); |
|
2564 |
LForInPrepareMap* result = new(zone()) LForInPrepareMap(context, object);
|
|
2511 | 2565 |
return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY); |
2512 | 2566 |
} |
2513 | 2567 |
|
Also available in: Unified diff