| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 arguments()->PrintTo(stream); | 379 arguments()->PrintTo(stream); |
| 380 | 380 |
| 381 stream->Add(" length "); | 381 stream->Add(" length "); |
| 382 length()->PrintTo(stream); | 382 length()->PrintTo(stream); |
| 383 | 383 |
| 384 stream->Add(" index "); | 384 stream->Add(" index "); |
| 385 index()->PrintTo(stream); | 385 index()->PrintTo(stream); |
| 386 } | 386 } |
| 387 | 387 |
| 388 | 388 |
| 389 int LPlatformChunk::GetNextSpillIndex(bool is_double) { | 389 int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) { |
| 390 // Skip a slot if for a double-width slot. | 390 // Skip a slot if for a double-width slot. |
| 391 if (is_double) { | 391 if (kind == DOUBLE_REGISTERS) { |
| 392 spill_slot_count_++; | 392 spill_slot_count_++; |
| 393 spill_slot_count_ |= 1; | 393 spill_slot_count_ |= 1; |
| 394 num_double_slots_++; | 394 num_double_slots_++; |
| 395 } | 395 } |
| 396 return spill_slot_count_++; | 396 return spill_slot_count_++; |
| 397 } | 397 } |
| 398 | 398 |
| 399 | 399 |
| 400 LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) { | 400 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) { |
| 401 int index = GetNextSpillIndex(is_double); | 401 int index = GetNextSpillIndex(kind); |
| 402 if (is_double) { | 402 if (kind == DOUBLE_REGISTERS) { |
| 403 return LDoubleStackSlot::Create(index, zone()); | 403 return LDoubleStackSlot::Create(index, zone()); |
| 404 } else { | 404 } else { |
| 405 ASSERT(kind == GENERAL_REGISTERS); |
| 405 return LStackSlot::Create(index, zone()); | 406 return LStackSlot::Create(index, zone()); |
| 406 } | 407 } |
| 407 } | 408 } |
| 408 | 409 |
| 409 | 410 |
| 410 void LStoreNamedField::PrintDataTo(StringStream* stream) { | 411 void LStoreNamedField::PrintDataTo(StringStream* stream) { |
| 411 object()->PrintTo(stream); | 412 object()->PrintTo(stream); |
| 412 hydrogen()->access().PrintTo(stream); | 413 hydrogen()->access().PrintTo(stream); |
| 413 stream->Add(" <- "); | 414 stream->Add(" <- "); |
| 414 value()->PrintTo(stream); | 415 value()->PrintTo(stream); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 | 473 |
| 473 | 474 |
| 474 LPlatformChunk* LChunkBuilder::Build() { | 475 LPlatformChunk* LChunkBuilder::Build() { |
| 475 ASSERT(is_unused()); | 476 ASSERT(is_unused()); |
| 476 chunk_ = new(zone()) LPlatformChunk(info(), graph()); | 477 chunk_ = new(zone()) LPlatformChunk(info(), graph()); |
| 477 LPhase phase("L_Building chunk", chunk_); | 478 LPhase phase("L_Building chunk", chunk_); |
| 478 status_ = BUILDING; | 479 status_ = BUILDING; |
| 479 | 480 |
| 480 // Reserve the first spill slot for the state of dynamic alignment. | 481 // Reserve the first spill slot for the state of dynamic alignment. |
| 481 if (info()->IsOptimizing()) { | 482 if (info()->IsOptimizing()) { |
| 482 int alignment_state_index = chunk_->GetNextSpillIndex(false); | 483 int alignment_state_index = chunk_->GetNextSpillIndex(GENERAL_REGISTERS); |
| 483 ASSERT_EQ(alignment_state_index, 0); | 484 ASSERT_EQ(alignment_state_index, 0); |
| 484 USE(alignment_state_index); | 485 USE(alignment_state_index); |
| 485 } | 486 } |
| 486 | 487 |
| 487 // If compiling for OSR, reserve space for the unoptimized frame, | 488 // If compiling for OSR, reserve space for the unoptimized frame, |
| 488 // which will be subsumed into this frame. | 489 // which will be subsumed into this frame. |
| 489 if (graph()->has_osr()) { | 490 if (graph()->has_osr()) { |
| 490 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) { | 491 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) { |
| 491 chunk_->GetNextSpillIndex(false); | 492 chunk_->GetNextSpillIndex(GENERAL_REGISTERS); |
| 492 } | 493 } |
| 493 } | 494 } |
| 494 | 495 |
| 495 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 496 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); |
| 496 for (int i = 0; i < blocks->length(); i++) { | 497 for (int i = 0; i < blocks->length(); i++) { |
| 497 HBasicBlock* next = NULL; | 498 HBasicBlock* next = NULL; |
| 498 if (i < blocks->length() - 1) next = blocks->at(i + 1); | 499 if (i < blocks->length() - 1) next = blocks->at(i + 1); |
| 499 DoBasicBlock(blocks->at(i), next); | 500 DoBasicBlock(blocks->at(i), next); |
| 500 if (is_aborted()) return NULL; | 501 if (is_aborted()) return NULL; |
| 501 } | 502 } |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 block->set_argument_count(argument_count_); | 902 block->set_argument_count(argument_count_); |
| 902 next_block_ = NULL; | 903 next_block_ = NULL; |
| 903 current_block_ = NULL; | 904 current_block_ = NULL; |
| 904 } | 905 } |
| 905 | 906 |
| 906 | 907 |
| 907 void LChunkBuilder::VisitInstruction(HInstruction* current) { | 908 void LChunkBuilder::VisitInstruction(HInstruction* current) { |
| 908 HInstruction* old_current = current_instruction_; | 909 HInstruction* old_current = current_instruction_; |
| 909 current_instruction_ = current; | 910 current_instruction_ = current; |
| 910 if (current->has_position()) position_ = current->position(); | 911 if (current->has_position()) position_ = current->position(); |
| 911 LInstruction* instr = current->CompileToLithium(this); | 912 |
| 913 LInstruction* instr = NULL; |
| 914 if (current->CanReplaceWithDummyUses()) { |
| 915 HValue* first_operand = current->OperandCount() == 0 |
| 916 ? graph()->GetConstant1() |
| 917 : current->OperandAt(0); |
| 918 instr = DefineAsRegister(new(zone()) LDummyUse(UseAny(first_operand))); |
| 919 for (int i = 1; i < current->OperandCount(); ++i) { |
| 920 LInstruction* dummy = |
| 921 new(zone()) LDummyUse(UseAny(current->OperandAt(i))); |
| 922 dummy->set_hydrogen_value(current); |
| 923 chunk_->AddInstruction(dummy, current_block_); |
| 924 } |
| 925 } else { |
| 926 instr = current->CompileToLithium(this); |
| 927 } |
| 928 |
| 929 argument_count_ += current->argument_delta(); |
| 930 ASSERT(argument_count_ >= 0); |
| 912 | 931 |
| 913 if (instr != NULL) { | 932 if (instr != NULL) { |
| 933 // Associate the hydrogen instruction first, since we may need it for |
| 934 // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below. |
| 935 instr->set_hydrogen_value(current); |
| 936 |
| 914 #if DEBUG | 937 #if DEBUG |
| 915 // Make sure that the lithium instruction has either no fixed register | 938 // Make sure that the lithium instruction has either no fixed register |
| 916 // constraints in temps or the result OR no uses that are only used at | 939 // constraints in temps or the result OR no uses that are only used at |
| 917 // start. If this invariant doesn't hold, the register allocator can decide | 940 // start. If this invariant doesn't hold, the register allocator can decide |
| 918 // to insert a split of a range immediately before the instruction due to an | 941 // to insert a split of a range immediately before the instruction due to an |
| 919 // already allocated register needing to be used for the instruction's fixed | 942 // already allocated register needing to be used for the instruction's fixed |
| 920 // register constraint. In this case, The register allocator won't see an | 943 // register constraint. In this case, The register allocator won't see an |
| 921 // interference between the split child and the use-at-start (it would if | 944 // interference between the split child and the use-at-start (it would if |
| 922 // the it was just a plain use), so it is free to move the split child into | 945 // the it was just a plain use), so it is free to move the split child into |
| 923 // the same register that is used for the use-at-start. | 946 // the same register that is used for the use-at-start. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 950 if (!CpuFeatures::IsSafeForSnapshot(SSE2) && instr->IsGoto() && | 973 if (!CpuFeatures::IsSafeForSnapshot(SSE2) && instr->IsGoto() && |
| 951 LGoto::cast(instr)->jumps_to_join()) { | 974 LGoto::cast(instr)->jumps_to_join()) { |
| 952 // TODO(olivf) Since phis of spilled values are joined as registers | 975 // TODO(olivf) Since phis of spilled values are joined as registers |
| 953 // (not in the stack slot), we need to allow the goto gaps to keep one | 976 // (not in the stack slot), we need to allow the goto gaps to keep one |
| 954 // x87 register alive. To ensure all other values are still spilled, we | 977 // x87 register alive. To ensure all other values are still spilled, we |
| 955 // insert a fpu register barrier right before. | 978 // insert a fpu register barrier right before. |
| 956 LClobberDoubles* clobber = new(zone()) LClobberDoubles(); | 979 LClobberDoubles* clobber = new(zone()) LClobberDoubles(); |
| 957 clobber->set_hydrogen_value(current); | 980 clobber->set_hydrogen_value(current); |
| 958 chunk_->AddInstruction(clobber, current_block_); | 981 chunk_->AddInstruction(clobber, current_block_); |
| 959 } | 982 } |
| 960 instr->set_hydrogen_value(current); | |
| 961 chunk_->AddInstruction(instr, current_block_); | 983 chunk_->AddInstruction(instr, current_block_); |
| 962 } | 984 } |
| 963 current_instruction_ = old_current; | 985 current_instruction_ = old_current; |
| 964 } | 986 } |
| 965 | 987 |
| 966 | 988 |
| 967 LEnvironment* LChunkBuilder::CreateEnvironment( | 989 LEnvironment* LChunkBuilder::CreateEnvironment( |
| 968 HEnvironment* hydrogen_env, | 990 HEnvironment* hydrogen_env, |
| 969 int* argument_index_accumulator, | 991 int* argument_index_accumulator, |
| 970 ZoneList<HValue*>* objects_to_materialize) { | 992 ZoneList<HValue*>* objects_to_materialize) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1047 return result; | 1069 return result; |
| 1048 } | 1070 } |
| 1049 | 1071 |
| 1050 | 1072 |
| 1051 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 1073 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
| 1052 return new(zone()) LGoto(instr->FirstSuccessor()); | 1074 return new(zone()) LGoto(instr->FirstSuccessor()); |
| 1053 } | 1075 } |
| 1054 | 1076 |
| 1055 | 1077 |
| 1056 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { | 1078 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
| 1057 HValue* value = instr->value(); | 1079 LInstruction* goto_instr = CheckElideControlInstruction(instr); |
| 1058 if (value->EmitAtUses()) { | 1080 if (goto_instr != NULL) return goto_instr; |
| 1059 ASSERT(value->IsConstant()); | |
| 1060 ASSERT(!value->representation().IsDouble()); | |
| 1061 HBasicBlock* successor = HConstant::cast(value)->BooleanValue() | |
| 1062 ? instr->FirstSuccessor() | |
| 1063 : instr->SecondSuccessor(); | |
| 1064 return new(zone()) LGoto(successor); | |
| 1065 } | |
| 1066 | 1081 |
| 1067 ToBooleanStub::Types expected = instr->expected_input_types(); | 1082 ToBooleanStub::Types expected = instr->expected_input_types(); |
| 1068 | 1083 |
| 1069 // Tagged values that are not known smis or booleans require a | 1084 // Tagged values that are not known smis or booleans require a |
| 1070 // deoptimization environment. If the instruction is generic no | 1085 // deoptimization environment. If the instruction is generic no |
| 1071 // environment is needed since all cases are handled. | 1086 // environment is needed since all cases are handled. |
| 1087 HValue* value = instr->value(); |
| 1072 Representation rep = value->representation(); | 1088 Representation rep = value->representation(); |
| 1073 HType type = value->type(); | 1089 HType type = value->type(); |
| 1074 if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) { | 1090 if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) { |
| 1075 return new(zone()) LBranch(UseRegister(value), NULL); | 1091 return new(zone()) LBranch(UseRegister(value), NULL); |
| 1076 } | 1092 } |
| 1077 | 1093 |
| 1078 bool needs_temp = expected.NeedsMap() || expected.IsEmpty(); | 1094 bool needs_temp = expected.NeedsMap() || expected.IsEmpty(); |
| 1079 LOperand* temp = needs_temp ? TempRegister() : NULL; | 1095 LOperand* temp = needs_temp ? TempRegister() : NULL; |
| 1080 | 1096 |
| 1081 // The Generic stub does not have a deopt, so we need no environment. | 1097 // The Generic stub does not have a deopt, so we need no environment. |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1157 LOperand* elements = UseFixed(instr->elements(), ecx); | 1173 LOperand* elements = UseFixed(instr->elements(), ecx); |
| 1158 LApplyArguments* result = new(zone()) LApplyArguments(function, | 1174 LApplyArguments* result = new(zone()) LApplyArguments(function, |
| 1159 receiver, | 1175 receiver, |
| 1160 length, | 1176 length, |
| 1161 elements); | 1177 elements); |
| 1162 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY); | 1178 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY); |
| 1163 } | 1179 } |
| 1164 | 1180 |
| 1165 | 1181 |
| 1166 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { | 1182 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { |
| 1167 ++argument_count_; | |
| 1168 LOperand* argument = UseAny(instr->argument()); | 1183 LOperand* argument = UseAny(instr->argument()); |
| 1169 return new(zone()) LPushArgument(argument); | 1184 return new(zone()) LPushArgument(argument); |
| 1170 } | 1185 } |
| 1171 | 1186 |
| 1172 | 1187 |
| 1173 LInstruction* LChunkBuilder::DoStoreCodeEntry( | 1188 LInstruction* LChunkBuilder::DoStoreCodeEntry( |
| 1174 HStoreCodeEntry* store_code_entry) { | 1189 HStoreCodeEntry* store_code_entry) { |
| 1175 LOperand* function = UseRegister(store_code_entry->function()); | 1190 LOperand* function = UseRegister(store_code_entry->function()); |
| 1176 LOperand* code_object = UseTempRegister(store_code_entry->code_object()); | 1191 LOperand* code_object = UseTempRegister(store_code_entry->code_object()); |
| 1177 return new(zone()) LStoreCodeEntry(function, code_object); | 1192 return new(zone()) LStoreCodeEntry(function, code_object); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1224 | 1239 |
| 1225 | 1240 |
| 1226 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) { | 1241 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) { |
| 1227 LOperand* global_object = UseRegisterAtStart(instr->value()); | 1242 LOperand* global_object = UseRegisterAtStart(instr->value()); |
| 1228 return DefineAsRegister(new(zone()) LGlobalReceiver(global_object)); | 1243 return DefineAsRegister(new(zone()) LGlobalReceiver(global_object)); |
| 1229 } | 1244 } |
| 1230 | 1245 |
| 1231 | 1246 |
| 1232 LInstruction* LChunkBuilder::DoCallConstantFunction( | 1247 LInstruction* LChunkBuilder::DoCallConstantFunction( |
| 1233 HCallConstantFunction* instr) { | 1248 HCallConstantFunction* instr) { |
| 1234 argument_count_ -= instr->argument_count(); | |
| 1235 return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, eax), instr); | 1249 return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, eax), instr); |
| 1236 } | 1250 } |
| 1237 | 1251 |
| 1238 | 1252 |
| 1239 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) { | 1253 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) { |
| 1240 LOperand* context = UseFixed(instr->context(), esi); | 1254 LOperand* context = UseFixed(instr->context(), esi); |
| 1241 LOperand* function = UseFixed(instr->function(), edi); | 1255 LOperand* function = UseFixed(instr->function(), edi); |
| 1242 argument_count_ -= instr->argument_count(); | |
| 1243 LInvokeFunction* result = new(zone()) LInvokeFunction(context, function); | 1256 LInvokeFunction* result = new(zone()) LInvokeFunction(context, function); |
| 1244 return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY); | 1257 return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY); |
| 1245 } | 1258 } |
| 1246 | 1259 |
| 1247 | 1260 |
| 1248 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { | 1261 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { |
| 1249 switch (instr->op()) { | 1262 switch (instr->op()) { |
| 1250 case kMathFloor: return DoMathFloor(instr); | 1263 case kMathFloor: return DoMathFloor(instr); |
| 1251 case kMathRound: return DoMathRound(instr); | 1264 case kMathRound: return DoMathRound(instr); |
| 1252 case kMathAbs: return DoMathAbs(instr); | 1265 case kMathAbs: return DoMathAbs(instr); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1342 LOperand* temp = TempRegister(); | 1355 LOperand* temp = TempRegister(); |
| 1343 LMathPowHalf* result = new(zone()) LMathPowHalf(context, input, temp); | 1356 LMathPowHalf* result = new(zone()) LMathPowHalf(context, input, temp); |
| 1344 return DefineSameAsFirst(result); | 1357 return DefineSameAsFirst(result); |
| 1345 } | 1358 } |
| 1346 | 1359 |
| 1347 | 1360 |
| 1348 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { | 1361 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { |
| 1349 ASSERT(instr->key()->representation().IsTagged()); | 1362 ASSERT(instr->key()->representation().IsTagged()); |
| 1350 LOperand* context = UseFixed(instr->context(), esi); | 1363 LOperand* context = UseFixed(instr->context(), esi); |
| 1351 LOperand* key = UseFixed(instr->key(), ecx); | 1364 LOperand* key = UseFixed(instr->key(), ecx); |
| 1352 argument_count_ -= instr->argument_count(); | |
| 1353 LCallKeyed* result = new(zone()) LCallKeyed(context, key); | 1365 LCallKeyed* result = new(zone()) LCallKeyed(context, key); |
| 1354 return MarkAsCall(DefineFixed(result, eax), instr); | 1366 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1355 } | 1367 } |
| 1356 | 1368 |
| 1357 | 1369 |
| 1358 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { | 1370 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { |
| 1359 LOperand* context = UseFixed(instr->context(), esi); | 1371 LOperand* context = UseFixed(instr->context(), esi); |
| 1360 argument_count_ -= instr->argument_count(); | |
| 1361 LCallNamed* result = new(zone()) LCallNamed(context); | 1372 LCallNamed* result = new(zone()) LCallNamed(context); |
| 1362 return MarkAsCall(DefineFixed(result, eax), instr); | 1373 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1363 } | 1374 } |
| 1364 | 1375 |
| 1365 | 1376 |
| 1366 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { | 1377 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { |
| 1367 LOperand* context = UseFixed(instr->context(), esi); | 1378 LOperand* context = UseFixed(instr->context(), esi); |
| 1368 argument_count_ -= instr->argument_count(); | |
| 1369 LCallGlobal* result = new(zone()) LCallGlobal(context); | 1379 LCallGlobal* result = new(zone()) LCallGlobal(context); |
| 1370 return MarkAsCall(DefineFixed(result, eax), instr); | 1380 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1371 } | 1381 } |
| 1372 | 1382 |
| 1373 | 1383 |
| 1374 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { | 1384 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { |
| 1375 argument_count_ -= instr->argument_count(); | |
| 1376 return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, eax), instr); | 1385 return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, eax), instr); |
| 1377 } | 1386 } |
| 1378 | 1387 |
| 1379 | 1388 |
| 1380 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { | 1389 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { |
| 1381 LOperand* context = UseFixed(instr->context(), esi); | 1390 LOperand* context = UseFixed(instr->context(), esi); |
| 1382 LOperand* constructor = UseFixed(instr->constructor(), edi); | 1391 LOperand* constructor = UseFixed(instr->constructor(), edi); |
| 1383 argument_count_ -= instr->argument_count(); | |
| 1384 LCallNew* result = new(zone()) LCallNew(context, constructor); | 1392 LCallNew* result = new(zone()) LCallNew(context, constructor); |
| 1385 return MarkAsCall(DefineFixed(result, eax), instr); | 1393 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1386 } | 1394 } |
| 1387 | 1395 |
| 1388 | 1396 |
| 1389 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) { | 1397 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) { |
| 1390 LOperand* context = UseFixed(instr->context(), esi); | 1398 LOperand* context = UseFixed(instr->context(), esi); |
| 1391 LOperand* constructor = UseFixed(instr->constructor(), edi); | 1399 LOperand* constructor = UseFixed(instr->constructor(), edi); |
| 1392 argument_count_ -= instr->argument_count(); | |
| 1393 LCallNewArray* result = new(zone()) LCallNewArray(context, constructor); | 1400 LCallNewArray* result = new(zone()) LCallNewArray(context, constructor); |
| 1394 return MarkAsCall(DefineFixed(result, eax), instr); | 1401 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1395 } | 1402 } |
| 1396 | 1403 |
| 1397 | 1404 |
| 1398 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { | 1405 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { |
| 1399 LOperand* context = UseFixed(instr->context(), esi); | 1406 LOperand* context = UseFixed(instr->context(), esi); |
| 1400 LOperand* function = UseFixed(instr->function(), edi); | 1407 LOperand* function = UseFixed(instr->function(), edi); |
| 1401 argument_count_ -= instr->argument_count(); | |
| 1402 LCallFunction* result = new(zone()) LCallFunction(context, function); | 1408 LCallFunction* result = new(zone()) LCallFunction(context, function); |
| 1403 return MarkAsCall(DefineFixed(result, eax), instr); | 1409 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1404 } | 1410 } |
| 1405 | 1411 |
| 1406 | 1412 |
| 1407 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { | 1413 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { |
| 1408 argument_count_ -= instr->argument_count(); | |
| 1409 LOperand* context = UseFixed(instr->context(), esi); | 1414 LOperand* context = UseFixed(instr->context(), esi); |
| 1410 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), eax), instr); | 1415 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), eax), instr); |
| 1411 } | 1416 } |
| 1412 | 1417 |
| 1413 | 1418 |
| 1414 LInstruction* LChunkBuilder::DoRor(HRor* instr) { | 1419 LInstruction* LChunkBuilder::DoRor(HRor* instr) { |
| 1415 return DoShift(Token::ROR, instr); | 1420 return DoShift(Token::ROR, instr); |
| 1416 } | 1421 } |
| 1417 | 1422 |
| 1418 | 1423 |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1733 left = UseRegisterAtStart(instr->left()); | 1738 left = UseRegisterAtStart(instr->left()); |
| 1734 right = UseRegisterAtStart(instr->right()); | 1739 right = UseRegisterAtStart(instr->right()); |
| 1735 } | 1740 } |
| 1736 return new(zone()) LCompareNumericAndBranch(left, right); | 1741 return new(zone()) LCompareNumericAndBranch(left, right); |
| 1737 } | 1742 } |
| 1738 } | 1743 } |
| 1739 | 1744 |
| 1740 | 1745 |
| 1741 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( | 1746 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( |
| 1742 HCompareObjectEqAndBranch* instr) { | 1747 HCompareObjectEqAndBranch* instr) { |
| 1748 LInstruction* goto_instr = CheckElideControlInstruction(instr); |
| 1749 if (goto_instr != NULL) return goto_instr; |
| 1743 LOperand* left = UseRegisterAtStart(instr->left()); | 1750 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1744 LOperand* right = UseOrConstantAtStart(instr->right()); | 1751 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1745 return new(zone()) LCmpObjectEqAndBranch(left, right); | 1752 return new(zone()) LCmpObjectEqAndBranch(left, right); |
| 1746 } | 1753 } |
| 1747 | 1754 |
| 1748 | 1755 |
| 1749 LInstruction* LChunkBuilder::DoCompareHoleAndBranch( | 1756 LInstruction* LChunkBuilder::DoCompareHoleAndBranch( |
| 1750 HCompareHoleAndBranch* instr) { | 1757 HCompareHoleAndBranch* instr) { |
| 1751 LOperand* value = UseRegisterAtStart(instr->value()); | 1758 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1752 return new(zone()) LCmpHoleAndBranch(value); | 1759 return new(zone()) LCmpHoleAndBranch(value); |
| (...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2408 obj = needs_write_barrier_for_map | 2415 obj = needs_write_barrier_for_map |
| 2409 ? UseRegister(instr->object()) | 2416 ? UseRegister(instr->object()) |
| 2410 : UseRegisterAtStart(instr->object()); | 2417 : UseRegisterAtStart(instr->object()); |
| 2411 } | 2418 } |
| 2412 | 2419 |
| 2413 bool can_be_constant = instr->value()->IsConstant() && | 2420 bool can_be_constant = instr->value()->IsConstant() && |
| 2414 HConstant::cast(instr->value())->NotInNewSpace() && | 2421 HConstant::cast(instr->value())->NotInNewSpace() && |
| 2415 !(FLAG_track_double_fields && instr->field_representation().IsDouble()); | 2422 !(FLAG_track_double_fields && instr->field_representation().IsDouble()); |
| 2416 | 2423 |
| 2417 LOperand* val; | 2424 LOperand* val; |
| 2418 if (needs_write_barrier) { | 2425 if (instr->field_representation().IsByte()) { |
| 2426 // mov_b requires a byte register (i.e. any of eax, ebx, ecx, edx). |
| 2427 // Just force the value to be in eax and we're safe here. |
| 2428 val = UseFixed(instr->value(), eax); |
| 2429 } else if (needs_write_barrier) { |
| 2419 val = UseTempRegister(instr->value()); | 2430 val = UseTempRegister(instr->value()); |
| 2420 } else if (can_be_constant) { | 2431 } else if (can_be_constant) { |
| 2421 val = UseRegisterOrConstant(instr->value()); | 2432 val = UseRegisterOrConstant(instr->value()); |
| 2422 } else if (FLAG_track_fields && instr->field_representation().IsSmi()) { | 2433 } else if (FLAG_track_fields && instr->field_representation().IsSmi()) { |
| 2423 val = UseTempRegister(instr->value()); | 2434 val = UseTempRegister(instr->value()); |
| 2424 } else if (FLAG_track_double_fields && | 2435 } else if (FLAG_track_double_fields && |
| 2425 instr->field_representation().IsDouble()) { | 2436 instr->field_representation().IsDouble()) { |
| 2426 val = UseRegisterAtStart(instr->value()); | 2437 val = UseRegisterAtStart(instr->value()); |
| 2427 } else { | 2438 } else { |
| 2428 val = UseRegister(instr->value()); | 2439 val = UseRegister(instr->value()); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2555 // The first local is saved at the end of the unoptimized frame. | 2566 // The first local is saved at the end of the unoptimized frame. |
| 2556 spill_index = graph()->osr()->UnoptimizedFrameSlots(); | 2567 spill_index = graph()->osr()->UnoptimizedFrameSlots(); |
| 2557 } | 2568 } |
| 2558 } | 2569 } |
| 2559 return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index); | 2570 return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index); |
| 2560 } | 2571 } |
| 2561 | 2572 |
| 2562 | 2573 |
| 2563 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { | 2574 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { |
| 2564 LOperand* context = UseFixed(instr->context(), esi); | 2575 LOperand* context = UseFixed(instr->context(), esi); |
| 2565 argument_count_ -= instr->argument_count(); | |
| 2566 LCallStub* result = new(zone()) LCallStub(context); | 2576 LCallStub* result = new(zone()) LCallStub(context); |
| 2567 return MarkAsCall(DefineFixed(result, eax), instr); | 2577 return MarkAsCall(DefineFixed(result, eax), instr); |
| 2568 } | 2578 } |
| 2569 | 2579 |
| 2570 | 2580 |
| 2571 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { | 2581 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { |
| 2572 // There are no real uses of the arguments object. | 2582 // There are no real uses of the arguments object. |
| 2573 // arguments.length and element access are supported directly on | 2583 // arguments.length and element access are supported directly on |
| 2574 // stack arguments, and any real arguments object use causes a bailout. | 2584 // stack arguments, and any real arguments object use causes a bailout. |
| 2575 // So this value is never used. | 2585 // So this value is never used. |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2684 | 2694 |
| 2685 | 2695 |
| 2686 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 2696 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 2687 LInstruction* pop = NULL; | 2697 LInstruction* pop = NULL; |
| 2688 | 2698 |
| 2689 HEnvironment* env = current_block_->last_environment(); | 2699 HEnvironment* env = current_block_->last_environment(); |
| 2690 | 2700 |
| 2691 if (env->entry()->arguments_pushed()) { | 2701 if (env->entry()->arguments_pushed()) { |
| 2692 int argument_count = env->arguments_environment()->parameter_count(); | 2702 int argument_count = env->arguments_environment()->parameter_count(); |
| 2693 pop = new(zone()) LDrop(argument_count); | 2703 pop = new(zone()) LDrop(argument_count); |
| 2694 argument_count_ -= argument_count; | 2704 ASSERT(instr->argument_delta() == -argument_count); |
| 2695 } | 2705 } |
| 2696 | 2706 |
| 2697 HEnvironment* outer = current_block_->last_environment()-> | 2707 HEnvironment* outer = current_block_->last_environment()-> |
| 2698 DiscardInlined(false); | 2708 DiscardInlined(false); |
| 2699 current_block_->UpdateEnvironment(outer); | 2709 current_block_->UpdateEnvironment(outer); |
| 2700 return pop; | 2710 return pop; |
| 2701 } | 2711 } |
| 2702 | 2712 |
| 2703 | 2713 |
| 2704 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) { | 2714 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2726 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2736 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2727 LOperand* object = UseRegister(instr->object()); | 2737 LOperand* object = UseRegister(instr->object()); |
| 2728 LOperand* index = UseTempRegister(instr->index()); | 2738 LOperand* index = UseTempRegister(instr->index()); |
| 2729 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); | 2739 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); |
| 2730 } | 2740 } |
| 2731 | 2741 |
| 2732 | 2742 |
| 2733 } } // namespace v8::internal | 2743 } } // namespace v8::internal |
| 2734 | 2744 |
| 2735 #endif // V8_TARGET_ARCH_IA32 | 2745 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |