| 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 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 arguments()->PrintTo(stream); | 346 arguments()->PrintTo(stream); |
| 347 | 347 |
| 348 stream->Add(" length "); | 348 stream->Add(" length "); |
| 349 length()->PrintTo(stream); | 349 length()->PrintTo(stream); |
| 350 | 350 |
| 351 stream->Add(" index "); | 351 stream->Add(" index "); |
| 352 index()->PrintTo(stream); | 352 index()->PrintTo(stream); |
| 353 } | 353 } |
| 354 | 354 |
| 355 | 355 |
| 356 int LPlatformChunk::GetNextSpillIndex(bool is_double) { | 356 int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) { |
| 357 return spill_slot_count_++; | 357 return spill_slot_count_++; |
| 358 } | 358 } |
| 359 | 359 |
| 360 | 360 |
| 361 LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) { | 361 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) { |
| 362 // All stack slots are Double stack slots on x64. | 362 // All stack slots are Double stack slots on x64. |
| 363 // Alternatively, at some point, start using half-size | 363 // Alternatively, at some point, start using half-size |
| 364 // stack slots for int32 values. | 364 // stack slots for int32 values. |
| 365 int index = GetNextSpillIndex(is_double); | 365 int index = GetNextSpillIndex(kind); |
| 366 if (is_double) { | 366 if (kind == DOUBLE_REGISTERS) { |
| 367 return LDoubleStackSlot::Create(index, zone()); | 367 return LDoubleStackSlot::Create(index, zone()); |
| 368 } else { | 368 } else { |
| 369 ASSERT(kind == GENERAL_REGISTERS); |
| 369 return LStackSlot::Create(index, zone()); | 370 return LStackSlot::Create(index, zone()); |
| 370 } | 371 } |
| 371 } | 372 } |
| 372 | 373 |
| 373 | 374 |
| 374 void LStoreNamedField::PrintDataTo(StringStream* stream) { | 375 void LStoreNamedField::PrintDataTo(StringStream* stream) { |
| 375 object()->PrintTo(stream); | 376 object()->PrintTo(stream); |
| 376 hydrogen()->access().PrintTo(stream); | 377 hydrogen()->access().PrintTo(stream); |
| 377 stream->Add(" <- "); | 378 stream->Add(" <- "); |
| 378 value()->PrintTo(stream); | 379 value()->PrintTo(stream); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 LPlatformChunk* LChunkBuilder::Build() { | 439 LPlatformChunk* LChunkBuilder::Build() { |
| 439 ASSERT(is_unused()); | 440 ASSERT(is_unused()); |
| 440 chunk_ = new(zone()) LPlatformChunk(info(), graph()); | 441 chunk_ = new(zone()) LPlatformChunk(info(), graph()); |
| 441 LPhase phase("L_Building chunk", chunk_); | 442 LPhase phase("L_Building chunk", chunk_); |
| 442 status_ = BUILDING; | 443 status_ = BUILDING; |
| 443 | 444 |
| 444 // If compiling for OSR, reserve space for the unoptimized frame, | 445 // If compiling for OSR, reserve space for the unoptimized frame, |
| 445 // which will be subsumed into this frame. | 446 // which will be subsumed into this frame. |
| 446 if (graph()->has_osr()) { | 447 if (graph()->has_osr()) { |
| 447 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) { | 448 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) { |
| 448 chunk_->GetNextSpillIndex(false); | 449 chunk_->GetNextSpillIndex(GENERAL_REGISTERS); |
| 449 } | 450 } |
| 450 } | 451 } |
| 451 | 452 |
| 452 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 453 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); |
| 453 for (int i = 0; i < blocks->length(); i++) { | 454 for (int i = 0; i < blocks->length(); i++) { |
| 454 HBasicBlock* next = NULL; | 455 HBasicBlock* next = NULL; |
| 455 if (i < blocks->length() - 1) next = blocks->at(i + 1); | 456 if (i < blocks->length() - 1) next = blocks->at(i + 1); |
| 456 DoBasicBlock(blocks->at(i), next); | 457 DoBasicBlock(blocks->at(i), next); |
| 457 if (is_aborted()) return NULL; | 458 if (is_aborted()) return NULL; |
| 458 } | 459 } |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 block->set_argument_count(argument_count_); | 853 block->set_argument_count(argument_count_); |
| 853 next_block_ = NULL; | 854 next_block_ = NULL; |
| 854 current_block_ = NULL; | 855 current_block_ = NULL; |
| 855 } | 856 } |
| 856 | 857 |
| 857 | 858 |
| 858 void LChunkBuilder::VisitInstruction(HInstruction* current) { | 859 void LChunkBuilder::VisitInstruction(HInstruction* current) { |
| 859 HInstruction* old_current = current_instruction_; | 860 HInstruction* old_current = current_instruction_; |
| 860 current_instruction_ = current; | 861 current_instruction_ = current; |
| 861 if (current->has_position()) position_ = current->position(); | 862 if (current->has_position()) position_ = current->position(); |
| 862 LInstruction* instr = current->CompileToLithium(this); | 863 |
| 864 LInstruction* instr = NULL; |
| 865 if (current->CanReplaceWithDummyUses()) { |
| 866 HValue* first_operand = current->OperandCount() == 0 |
| 867 ? graph()->GetConstant1() |
| 868 : current->OperandAt(0); |
| 869 instr = DefineAsRegister(new(zone()) LDummyUse(UseAny(first_operand))); |
| 870 for (int i = 1; i < current->OperandCount(); ++i) { |
| 871 LInstruction* dummy = |
| 872 new(zone()) LDummyUse(UseAny(current->OperandAt(i))); |
| 873 dummy->set_hydrogen_value(current); |
| 874 chunk_->AddInstruction(dummy, current_block_); |
| 875 } |
| 876 } else { |
| 877 instr = current->CompileToLithium(this); |
| 878 } |
| 879 |
| 880 argument_count_ += current->argument_delta(); |
| 881 ASSERT(argument_count_ >= 0); |
| 863 | 882 |
| 864 if (instr != NULL) { | 883 if (instr != NULL) { |
| 884 // Associate the hydrogen instruction first, since we may need it for |
| 885 // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below. |
| 886 instr->set_hydrogen_value(current); |
| 887 |
| 865 #if DEBUG | 888 #if DEBUG |
| 866 // Make sure that the lithium instruction has either no fixed register | 889 // Make sure that the lithium instruction has either no fixed register |
| 867 // constraints in temps or the result OR no uses that are only used at | 890 // constraints in temps or the result OR no uses that are only used at |
| 868 // start. If this invariant doesn't hold, the register allocator can decide | 891 // start. If this invariant doesn't hold, the register allocator can decide |
| 869 // to insert a split of a range immediately before the instruction due to an | 892 // to insert a split of a range immediately before the instruction due to an |
| 870 // already allocated register needing to be used for the instruction's fixed | 893 // already allocated register needing to be used for the instruction's fixed |
| 871 // register constraint. In this case, The register allocator won't see an | 894 // register constraint. In this case, The register allocator won't see an |
| 872 // interference between the split child and the use-at-start (it would if | 895 // interference between the split child and the use-at-start (it would if |
| 873 // the it was just a plain use), so it is free to move the split child into | 896 // the it was just a plain use), so it is free to move the split child into |
| 874 // the same register that is used for the use-at-start. | 897 // the same register that is used for the use-at-start. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 891 } | 914 } |
| 892 #endif | 915 #endif |
| 893 | 916 |
| 894 instr->set_position(position_); | 917 instr->set_position(position_); |
| 895 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { | 918 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
| 896 instr = AssignPointerMap(instr); | 919 instr = AssignPointerMap(instr); |
| 897 } | 920 } |
| 898 if (FLAG_stress_environments && !instr->HasEnvironment()) { | 921 if (FLAG_stress_environments && !instr->HasEnvironment()) { |
| 899 instr = AssignEnvironment(instr); | 922 instr = AssignEnvironment(instr); |
| 900 } | 923 } |
| 901 instr->set_hydrogen_value(current); | |
| 902 chunk_->AddInstruction(instr, current_block_); | 924 chunk_->AddInstruction(instr, current_block_); |
| 903 } | 925 } |
| 904 current_instruction_ = old_current; | 926 current_instruction_ = old_current; |
| 905 } | 927 } |
| 906 | 928 |
| 907 | 929 |
| 908 LEnvironment* LChunkBuilder::CreateEnvironment( | 930 LEnvironment* LChunkBuilder::CreateEnvironment( |
| 909 HEnvironment* hydrogen_env, | 931 HEnvironment* hydrogen_env, |
| 910 int* argument_index_accumulator, | 932 int* argument_index_accumulator, |
| 911 ZoneList<HValue*>* objects_to_materialize) { | 933 ZoneList<HValue*>* objects_to_materialize) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 983 | 1005 |
| 984 if (hydrogen_env->frame_type() == JS_FUNCTION) { | 1006 if (hydrogen_env->frame_type() == JS_FUNCTION) { |
| 985 *argument_index_accumulator = argument_index; | 1007 *argument_index_accumulator = argument_index; |
| 986 } | 1008 } |
| 987 | 1009 |
| 988 return result; | 1010 return result; |
| 989 } | 1011 } |
| 990 | 1012 |
| 991 | 1013 |
| 992 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 1014 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
| 993 return new(zone()) LGoto(instr->FirstSuccessor()->block_id()); | 1015 return new(zone()) LGoto(instr->FirstSuccessor()); |
| 994 } | 1016 } |
| 995 | 1017 |
| 996 | 1018 |
| 997 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { | 1019 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { |
| 998 return new(zone()) LDebugBreak(); | 1020 return new(zone()) LDebugBreak(); |
| 999 } | 1021 } |
| 1000 | 1022 |
| 1001 | 1023 |
| 1002 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { | 1024 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
| 1025 LInstruction* goto_instr = CheckElideControlInstruction(instr); |
| 1026 if (goto_instr != NULL) return goto_instr; |
| 1027 |
| 1003 HValue* value = instr->value(); | 1028 HValue* value = instr->value(); |
| 1004 if (value->EmitAtUses()) { | |
| 1005 ASSERT(value->IsConstant()); | |
| 1006 ASSERT(!value->representation().IsDouble()); | |
| 1007 HBasicBlock* successor = HConstant::cast(value)->BooleanValue() | |
| 1008 ? instr->FirstSuccessor() | |
| 1009 : instr->SecondSuccessor(); | |
| 1010 return new(zone()) LGoto(successor->block_id()); | |
| 1011 } | |
| 1012 | |
| 1013 LBranch* result = new(zone()) LBranch(UseRegister(value)); | 1029 LBranch* result = new(zone()) LBranch(UseRegister(value)); |
| 1014 // Tagged values that are not known smis or booleans require a | 1030 // Tagged values that are not known smis or booleans require a |
| 1015 // deoptimization environment. If the instruction is generic no | 1031 // deoptimization environment. If the instruction is generic no |
| 1016 // environment is needed since all cases are handled. | 1032 // environment is needed since all cases are handled. |
| 1017 ToBooleanStub::Types expected = instr->expected_input_types(); | 1033 ToBooleanStub::Types expected = instr->expected_input_types(); |
| 1018 Representation rep = value->representation(); | 1034 Representation rep = value->representation(); |
| 1019 HType type = value->type(); | 1035 HType type = value->type(); |
| 1020 if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean() && | 1036 if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean() && |
| 1021 !expected.IsGeneric()) { | 1037 !expected.IsGeneric()) { |
| 1022 return AssignEnvironment(result); | 1038 return AssignEnvironment(result); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1082 LOperand* elements = UseFixed(instr->elements(), rcx); | 1098 LOperand* elements = UseFixed(instr->elements(), rcx); |
| 1083 LApplyArguments* result = new(zone()) LApplyArguments(function, | 1099 LApplyArguments* result = new(zone()) LApplyArguments(function, |
| 1084 receiver, | 1100 receiver, |
| 1085 length, | 1101 length, |
| 1086 elements); | 1102 elements); |
| 1087 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY); | 1103 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY); |
| 1088 } | 1104 } |
| 1089 | 1105 |
| 1090 | 1106 |
| 1091 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { | 1107 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { |
| 1092 ++argument_count_; | |
| 1093 LOperand* argument = UseOrConstant(instr->argument()); | 1108 LOperand* argument = UseOrConstant(instr->argument()); |
| 1094 return new(zone()) LPushArgument(argument); | 1109 return new(zone()) LPushArgument(argument); |
| 1095 } | 1110 } |
| 1096 | 1111 |
| 1097 | 1112 |
| 1098 LInstruction* LChunkBuilder::DoStoreCodeEntry( | 1113 LInstruction* LChunkBuilder::DoStoreCodeEntry( |
| 1099 HStoreCodeEntry* store_code_entry) { | 1114 HStoreCodeEntry* store_code_entry) { |
| 1100 LOperand* function = UseRegister(store_code_entry->function()); | 1115 LOperand* function = UseRegister(store_code_entry->function()); |
| 1101 LOperand* code_object = UseTempRegister(store_code_entry->code_object()); | 1116 LOperand* code_object = UseTempRegister(store_code_entry->code_object()); |
| 1102 return new(zone()) LStoreCodeEntry(function, code_object); | 1117 return new(zone()) LStoreCodeEntry(function, code_object); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1148 | 1163 |
| 1149 | 1164 |
| 1150 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) { | 1165 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) { |
| 1151 LOperand* global_object = UseRegisterAtStart(instr->value()); | 1166 LOperand* global_object = UseRegisterAtStart(instr->value()); |
| 1152 return DefineAsRegister(new(zone()) LGlobalReceiver(global_object)); | 1167 return DefineAsRegister(new(zone()) LGlobalReceiver(global_object)); |
| 1153 } | 1168 } |
| 1154 | 1169 |
| 1155 | 1170 |
| 1156 LInstruction* LChunkBuilder::DoCallConstantFunction( | 1171 LInstruction* LChunkBuilder::DoCallConstantFunction( |
| 1157 HCallConstantFunction* instr) { | 1172 HCallConstantFunction* instr) { |
| 1158 argument_count_ -= instr->argument_count(); | |
| 1159 return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, rax), instr); | 1173 return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, rax), instr); |
| 1160 } | 1174 } |
| 1161 | 1175 |
| 1162 | 1176 |
| 1163 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) { | 1177 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) { |
| 1164 LOperand* function = UseFixed(instr->function(), rdi); | 1178 LOperand* function = UseFixed(instr->function(), rdi); |
| 1165 argument_count_ -= instr->argument_count(); | |
| 1166 LInvokeFunction* result = new(zone()) LInvokeFunction(function); | 1179 LInvokeFunction* result = new(zone()) LInvokeFunction(function); |
| 1167 return MarkAsCall(DefineFixed(result, rax), instr, CANNOT_DEOPTIMIZE_EAGERLY); | 1180 return MarkAsCall(DefineFixed(result, rax), instr, CANNOT_DEOPTIMIZE_EAGERLY); |
| 1168 } | 1181 } |
| 1169 | 1182 |
| 1170 | 1183 |
| 1171 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { | 1184 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { |
| 1172 switch (instr->op()) { | 1185 switch (instr->op()) { |
| 1173 case kMathFloor: return DoMathFloor(instr); | 1186 case kMathFloor: return DoMathFloor(instr); |
| 1174 case kMathRound: return DoMathRound(instr); | 1187 case kMathRound: return DoMathRound(instr); |
| 1175 case kMathAbs: return DoMathAbs(instr); | 1188 case kMathAbs: return DoMathAbs(instr); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1257 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) { | 1270 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) { |
| 1258 LOperand* input = UseRegisterAtStart(instr->value()); | 1271 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1259 LMathPowHalf* result = new(zone()) LMathPowHalf(input); | 1272 LMathPowHalf* result = new(zone()) LMathPowHalf(input); |
| 1260 return DefineSameAsFirst(result); | 1273 return DefineSameAsFirst(result); |
| 1261 } | 1274 } |
| 1262 | 1275 |
| 1263 | 1276 |
| 1264 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { | 1277 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { |
| 1265 ASSERT(instr->key()->representation().IsTagged()); | 1278 ASSERT(instr->key()->representation().IsTagged()); |
| 1266 LOperand* key = UseFixed(instr->key(), rcx); | 1279 LOperand* key = UseFixed(instr->key(), rcx); |
| 1267 argument_count_ -= instr->argument_count(); | |
| 1268 LCallKeyed* result = new(zone()) LCallKeyed(key); | 1280 LCallKeyed* result = new(zone()) LCallKeyed(key); |
| 1269 return MarkAsCall(DefineFixed(result, rax), instr); | 1281 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1270 } | 1282 } |
| 1271 | 1283 |
| 1272 | 1284 |
| 1273 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { | 1285 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { |
| 1274 argument_count_ -= instr->argument_count(); | |
| 1275 return MarkAsCall(DefineFixed(new(zone()) LCallNamed, rax), instr); | 1286 return MarkAsCall(DefineFixed(new(zone()) LCallNamed, rax), instr); |
| 1276 } | 1287 } |
| 1277 | 1288 |
| 1278 | 1289 |
| 1279 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { | 1290 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { |
| 1280 argument_count_ -= instr->argument_count(); | |
| 1281 return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, rax), instr); | 1291 return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, rax), instr); |
| 1282 } | 1292 } |
| 1283 | 1293 |
| 1284 | 1294 |
| 1285 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { | 1295 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { |
| 1286 argument_count_ -= instr->argument_count(); | |
| 1287 return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, rax), instr); | 1296 return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, rax), instr); |
| 1288 } | 1297 } |
| 1289 | 1298 |
| 1290 | 1299 |
| 1291 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { | 1300 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { |
| 1292 LOperand* constructor = UseFixed(instr->constructor(), rdi); | 1301 LOperand* constructor = UseFixed(instr->constructor(), rdi); |
| 1293 argument_count_ -= instr->argument_count(); | |
| 1294 LCallNew* result = new(zone()) LCallNew(constructor); | 1302 LCallNew* result = new(zone()) LCallNew(constructor); |
| 1295 return MarkAsCall(DefineFixed(result, rax), instr); | 1303 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1296 } | 1304 } |
| 1297 | 1305 |
| 1298 | 1306 |
| 1299 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) { | 1307 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) { |
| 1300 LOperand* constructor = UseFixed(instr->constructor(), rdi); | 1308 LOperand* constructor = UseFixed(instr->constructor(), rdi); |
| 1301 argument_count_ -= instr->argument_count(); | |
| 1302 LCallNewArray* result = new(zone()) LCallNewArray(constructor); | 1309 LCallNewArray* result = new(zone()) LCallNewArray(constructor); |
| 1303 return MarkAsCall(DefineFixed(result, rax), instr); | 1310 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1304 } | 1311 } |
| 1305 | 1312 |
| 1306 | 1313 |
| 1307 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { | 1314 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { |
| 1308 LOperand* function = UseFixed(instr->function(), rdi); | 1315 LOperand* function = UseFixed(instr->function(), rdi); |
| 1309 argument_count_ -= instr->argument_count(); | |
| 1310 LCallFunction* result = new(zone()) LCallFunction(function); | 1316 LCallFunction* result = new(zone()) LCallFunction(function); |
| 1311 return MarkAsCall(DefineFixed(result, rax), instr); | 1317 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1312 } | 1318 } |
| 1313 | 1319 |
| 1314 | 1320 |
| 1315 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { | 1321 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { |
| 1316 argument_count_ -= instr->argument_count(); | |
| 1317 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, rax), instr); | 1322 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, rax), instr); |
| 1318 } | 1323 } |
| 1319 | 1324 |
| 1320 | 1325 |
| 1321 LInstruction* LChunkBuilder::DoRor(HRor* instr) { | 1326 LInstruction* LChunkBuilder::DoRor(HRor* instr) { |
| 1322 return DoShift(Token::ROR, instr); | 1327 return DoShift(Token::ROR, instr); |
| 1323 } | 1328 } |
| 1324 | 1329 |
| 1325 | 1330 |
| 1326 LInstruction* LChunkBuilder::DoShr(HShr* instr) { | 1331 LInstruction* LChunkBuilder::DoShr(HShr* instr) { |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1632 left = UseRegisterAtStart(instr->left()); | 1637 left = UseRegisterAtStart(instr->left()); |
| 1633 right = UseRegisterAtStart(instr->right()); | 1638 right = UseRegisterAtStart(instr->right()); |
| 1634 } | 1639 } |
| 1635 return new(zone()) LCompareNumericAndBranch(left, right); | 1640 return new(zone()) LCompareNumericAndBranch(left, right); |
| 1636 } | 1641 } |
| 1637 } | 1642 } |
| 1638 | 1643 |
| 1639 | 1644 |
| 1640 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( | 1645 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( |
| 1641 HCompareObjectEqAndBranch* instr) { | 1646 HCompareObjectEqAndBranch* instr) { |
| 1647 LInstruction* goto_instr = CheckElideControlInstruction(instr); |
| 1648 if (goto_instr != NULL) return goto_instr; |
| 1642 LOperand* left = UseRegisterAtStart(instr->left()); | 1649 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1643 LOperand* right = UseRegisterOrConstantAtStart(instr->right()); | 1650 LOperand* right = UseRegisterOrConstantAtStart(instr->right()); |
| 1644 return new(zone()) LCmpObjectEqAndBranch(left, right); | 1651 return new(zone()) LCmpObjectEqAndBranch(left, right); |
| 1645 } | 1652 } |
| 1646 | 1653 |
| 1647 | 1654 |
| 1648 LInstruction* LChunkBuilder::DoCompareHoleAndBranch( | 1655 LInstruction* LChunkBuilder::DoCompareHoleAndBranch( |
| 1649 HCompareHoleAndBranch* instr) { | 1656 HCompareHoleAndBranch* instr) { |
| 1650 LOperand* value = UseRegisterAtStart(instr->value()); | 1657 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1651 return new(zone()) LCmpHoleAndBranch(value); | 1658 return new(zone()) LCmpHoleAndBranch(value); |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2046 context = UseRegister(instr->context()); | 2053 context = UseRegister(instr->context()); |
| 2047 value = UseRegister(instr->value()); | 2054 value = UseRegister(instr->value()); |
| 2048 temp = NULL; | 2055 temp = NULL; |
| 2049 } | 2056 } |
| 2050 LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp); | 2057 LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp); |
| 2051 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; | 2058 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; |
| 2052 } | 2059 } |
| 2053 | 2060 |
| 2054 | 2061 |
| 2055 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { | 2062 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { |
| 2056 if (instr->access().IsExternalMemory() && instr->access().offset() == 0) { | 2063 // Use the special mov rax, moffs64 encoding for external |
| 2064 // memory accesses with 64-bit word-sized values. |
| 2065 if (instr->access().IsExternalMemory() && |
| 2066 instr->access().offset() == 0 && |
| 2067 (instr->access().representation().IsSmi() || |
| 2068 instr->access().representation().IsTagged() || |
| 2069 instr->access().representation().IsHeapObject() || |
| 2070 instr->access().representation().IsExternal())) { |
| 2057 LOperand* obj = UseRegisterOrConstantAtStart(instr->object()); | 2071 LOperand* obj = UseRegisterOrConstantAtStart(instr->object()); |
| 2058 return DefineFixed(new(zone()) LLoadNamedField(obj), rax); | 2072 return DefineFixed(new(zone()) LLoadNamedField(obj), rax); |
| 2059 } | 2073 } |
| 2060 LOperand* obj = UseRegisterAtStart(instr->object()); | 2074 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 2061 return DefineAsRegister(new(zone()) LLoadNamedField(obj)); | 2075 return DefineAsRegister(new(zone()) LLoadNamedField(obj)); |
| 2062 } | 2076 } |
| 2063 | 2077 |
| 2064 | 2078 |
| 2065 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { | 2079 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { |
| 2066 LOperand* object = UseFixed(instr->object(), rax); | 2080 LOperand* object = UseFixed(instr->object(), rax); |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2367 if (spill_index > LUnallocated::kMaxFixedSlotIndex) { | 2381 if (spill_index > LUnallocated::kMaxFixedSlotIndex) { |
| 2368 Abort(kTooManySpillSlotsNeededForOSR); | 2382 Abort(kTooManySpillSlotsNeededForOSR); |
| 2369 spill_index = 0; | 2383 spill_index = 0; |
| 2370 } | 2384 } |
| 2371 } | 2385 } |
| 2372 return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index); | 2386 return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index); |
| 2373 } | 2387 } |
| 2374 | 2388 |
| 2375 | 2389 |
| 2376 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { | 2390 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { |
| 2377 argument_count_ -= instr->argument_count(); | |
| 2378 return MarkAsCall(DefineFixed(new(zone()) LCallStub, rax), instr); | 2391 return MarkAsCall(DefineFixed(new(zone()) LCallStub, rax), instr); |
| 2379 } | 2392 } |
| 2380 | 2393 |
| 2381 | 2394 |
| 2382 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { | 2395 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { |
| 2383 // There are no real uses of the arguments object. | 2396 // There are no real uses of the arguments object. |
| 2384 // arguments.length and element access are supported directly on | 2397 // arguments.length and element access are supported directly on |
| 2385 // stack arguments, and any real arguments object use causes a bailout. | 2398 // stack arguments, and any real arguments object use causes a bailout. |
| 2386 // So this value is never used. | 2399 // So this value is never used. |
| 2387 return NULL; | 2400 return NULL; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2489 | 2502 |
| 2490 | 2503 |
| 2491 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 2504 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 2492 LInstruction* pop = NULL; | 2505 LInstruction* pop = NULL; |
| 2493 | 2506 |
| 2494 HEnvironment* env = current_block_->last_environment(); | 2507 HEnvironment* env = current_block_->last_environment(); |
| 2495 | 2508 |
| 2496 if (env->entry()->arguments_pushed()) { | 2509 if (env->entry()->arguments_pushed()) { |
| 2497 int argument_count = env->arguments_environment()->parameter_count(); | 2510 int argument_count = env->arguments_environment()->parameter_count(); |
| 2498 pop = new(zone()) LDrop(argument_count); | 2511 pop = new(zone()) LDrop(argument_count); |
| 2499 argument_count_ -= argument_count; | 2512 ASSERT(instr->argument_delta() == -argument_count); |
| 2500 } | 2513 } |
| 2501 | 2514 |
| 2502 HEnvironment* outer = current_block_->last_environment()-> | 2515 HEnvironment* outer = current_block_->last_environment()-> |
| 2503 DiscardInlined(false); | 2516 DiscardInlined(false); |
| 2504 current_block_->UpdateEnvironment(outer); | 2517 current_block_->UpdateEnvironment(outer); |
| 2505 | 2518 |
| 2506 return pop; | 2519 return pop; |
| 2507 } | 2520 } |
| 2508 | 2521 |
| 2509 | 2522 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2531 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2544 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2532 LOperand* object = UseRegister(instr->object()); | 2545 LOperand* object = UseRegister(instr->object()); |
| 2533 LOperand* index = UseTempRegister(instr->index()); | 2546 LOperand* index = UseTempRegister(instr->index()); |
| 2534 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); | 2547 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); |
| 2535 } | 2548 } |
| 2536 | 2549 |
| 2537 | 2550 |
| 2538 } } // namespace v8::internal | 2551 } } // namespace v8::internal |
| 2539 | 2552 |
| 2540 #endif // V8_TARGET_ARCH_X64 | 2553 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |