| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 ASSERT(double_register_spills_[allocation_index] == NULL); | 67 ASSERT(double_register_spills_[allocation_index] == NULL); |
| 68 double_register_spills_[allocation_index] = spill_operand; | 68 double_register_spills_[allocation_index] = spill_operand; |
| 69 } | 69 } |
| 70 | 70 |
| 71 | 71 |
| 72 #ifdef DEBUG | 72 #ifdef DEBUG |
| 73 void LInstruction::VerifyCall() { | 73 void LInstruction::VerifyCall() { |
| 74 // Call instructions can use only fixed registers as | 74 // Call instructions can use only fixed registers as |
| 75 // temporaries and outputs because all registers | 75 // temporaries and outputs because all registers |
| 76 // are blocked by the calling convention. | 76 // are blocked by the calling convention. |
| 77 // Inputs can use either fixed register or have a short lifetime (be | 77 // Inputs must use a fixed register. |
| 78 // used at start of the instruction). | |
| 79 ASSERT(Output() == NULL || | 78 ASSERT(Output() == NULL || |
| 80 LUnallocated::cast(Output())->HasFixedPolicy() || | 79 LUnallocated::cast(Output())->HasFixedPolicy() || |
| 81 !LUnallocated::cast(Output())->HasRegisterPolicy()); | 80 !LUnallocated::cast(Output())->HasRegisterPolicy()); |
| 82 for (UseIterator it(this); it.HasNext(); it.Advance()) { | 81 for (UseIterator it(this); it.HasNext(); it.Advance()) { |
| 83 LOperand* operand = it.Next(); | 82 LOperand* operand = it.Next(); |
| 84 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() || | 83 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() || |
| 85 LUnallocated::cast(operand)->IsUsedAtStart() || | |
| 86 !LUnallocated::cast(operand)->HasRegisterPolicy()); | 84 !LUnallocated::cast(operand)->HasRegisterPolicy()); |
| 87 } | 85 } |
| 88 for (TempIterator it(this); it.HasNext(); it.Advance()) { | 86 for (TempIterator it(this); it.HasNext(); it.Advance()) { |
| 89 LOperand* operand = it.Next(); | 87 LOperand* operand = it.Next(); |
| 90 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() || | 88 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() || |
| 91 !LUnallocated::cast(operand)->HasRegisterPolicy()); | 89 !LUnallocated::cast(operand)->HasRegisterPolicy()); |
| 92 } | 90 } |
| 93 } | 91 } |
| 94 #endif | 92 #endif |
| 95 | 93 |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 InputAt(0)->PrintTo(stream); | 289 InputAt(0)->PrintTo(stream); |
| 292 } | 290 } |
| 293 | 291 |
| 294 | 292 |
| 295 void LLoadContextSlot::PrintDataTo(StringStream* stream) { | 293 void LLoadContextSlot::PrintDataTo(StringStream* stream) { |
| 296 InputAt(0)->PrintTo(stream); | 294 InputAt(0)->PrintTo(stream); |
| 297 stream->Add("[%d]", slot_index()); | 295 stream->Add("[%d]", slot_index()); |
| 298 } | 296 } |
| 299 | 297 |
| 300 | 298 |
| 299 void LStoreContextSlot::PrintDataTo(StringStream* stream) { |
| 300 InputAt(0)->PrintTo(stream); |
| 301 stream->Add("[%d] <- ", slot_index()); |
| 302 InputAt(1)->PrintTo(stream); |
| 303 } |
| 304 |
| 305 |
| 301 void LCallKeyed::PrintDataTo(StringStream* stream) { | 306 void LCallKeyed::PrintDataTo(StringStream* stream) { |
| 302 stream->Add("[ecx] #%d / ", arity()); | 307 stream->Add("[rcx] #%d / ", arity()); |
| 303 } | 308 } |
| 304 | 309 |
| 305 | 310 |
| 306 void LCallNamed::PrintDataTo(StringStream* stream) { | 311 void LCallNamed::PrintDataTo(StringStream* stream) { |
| 307 SmartPointer<char> name_string = name()->ToCString(); | 312 SmartPointer<char> name_string = name()->ToCString(); |
| 308 stream->Add("%s #%d / ", *name_string, arity()); | 313 stream->Add("%s #%d / ", *name_string, arity()); |
| 309 } | 314 } |
| 310 | 315 |
| 311 | 316 |
| 312 void LCallGlobal::PrintDataTo(StringStream* stream) { | 317 void LCallGlobal::PrintDataTo(StringStream* stream) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 | 398 |
| 394 if (can_eliminate) { | 399 if (can_eliminate) { |
| 395 label->set_replacement(GetLabel(goto_instr->block_id())); | 400 label->set_replacement(GetLabel(goto_instr->block_id())); |
| 396 } | 401 } |
| 397 } | 402 } |
| 398 } | 403 } |
| 399 } | 404 } |
| 400 } | 405 } |
| 401 | 406 |
| 402 | 407 |
| 403 void LStoreNamed::PrintDataTo(StringStream* stream) { | 408 void LStoreNamedField::PrintDataTo(StringStream* stream) { |
| 404 object()->PrintTo(stream); | 409 object()->PrintTo(stream); |
| 405 stream->Add("."); | 410 stream->Add("."); |
| 406 stream->Add(*String::cast(*name())->ToCString()); | 411 stream->Add(*String::cast(*name())->ToCString()); |
| 407 stream->Add(" <- "); | 412 stream->Add(" <- "); |
| 408 value()->PrintTo(stream); | 413 value()->PrintTo(stream); |
| 409 } | 414 } |
| 410 | 415 |
| 411 | 416 |
| 412 void LStoreKeyed::PrintDataTo(StringStream* stream) { | 417 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) { |
| 418 object()->PrintTo(stream); |
| 419 stream->Add("."); |
| 420 stream->Add(*String::cast(*name())->ToCString()); |
| 421 stream->Add(" <- "); |
| 422 value()->PrintTo(stream); |
| 423 } |
| 424 |
| 425 |
| 426 void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) { |
| 413 object()->PrintTo(stream); | 427 object()->PrintTo(stream); |
| 414 stream->Add("["); | 428 stream->Add("["); |
| 415 key()->PrintTo(stream); | 429 key()->PrintTo(stream); |
| 416 stream->Add("] <- "); | 430 stream->Add("] <- "); |
| 417 value()->PrintTo(stream); | 431 value()->PrintTo(stream); |
| 418 } | 432 } |
| 419 | 433 |
| 420 | 434 |
| 435 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) { |
| 436 object()->PrintTo(stream); |
| 437 stream->Add("["); |
| 438 key()->PrintTo(stream); |
| 439 stream->Add("] <- "); |
| 440 value()->PrintTo(stream); |
| 441 } |
| 442 |
| 443 |
| 421 void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { | 444 void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { |
| 422 LGap* gap = new LGap(block); | 445 LGap* gap = new LGap(block); |
| 423 int index = -1; | 446 int index = -1; |
| 424 if (instr->IsControl()) { | 447 if (instr->IsControl()) { |
| 425 instructions_.Add(gap); | 448 instructions_.Add(gap); |
| 426 index = instructions_.length(); | 449 index = instructions_.length(); |
| 427 instructions_.Add(instr); | 450 instructions_.Add(instr); |
| 428 } else { | 451 } else { |
| 429 index = instructions_.length(); | 452 index = instructions_.length(); |
| 430 instructions_.Add(instr); | 453 instructions_.Add(instr); |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 | 861 |
| 839 LShiftI* result = new LShiftI(op, left, right, can_deopt); | 862 LShiftI* result = new LShiftI(op, left, right, can_deopt); |
| 840 return can_deopt | 863 return can_deopt |
| 841 ? AssignEnvironment(DefineSameAsFirst(result)) | 864 ? AssignEnvironment(DefineSameAsFirst(result)) |
| 842 : DefineSameAsFirst(result); | 865 : DefineSameAsFirst(result); |
| 843 } | 866 } |
| 844 | 867 |
| 845 | 868 |
| 846 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, | 869 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, |
| 847 HArithmeticBinaryOperation* instr) { | 870 HArithmeticBinaryOperation* instr) { |
| 848 Abort("Unimplemented: %s", "DoArithmeticD"); | 871 ASSERT(instr->representation().IsDouble()); |
| 849 return NULL; | 872 ASSERT(instr->left()->representation().IsDouble()); |
| 873 ASSERT(instr->right()->representation().IsDouble()); |
| 874 ASSERT(op != Token::MOD); |
| 875 LOperand* left = UseRegisterAtStart(instr->left()); |
| 876 LOperand* right = UseRegisterAtStart(instr->right()); |
| 877 LArithmeticD* result = new LArithmeticD(op, left, right); |
| 878 return DefineSameAsFirst(result); |
| 850 } | 879 } |
| 851 | 880 |
| 852 | 881 |
| 853 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 882 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
| 854 HArithmeticBinaryOperation* instr) { | 883 HArithmeticBinaryOperation* instr) { |
| 855 ASSERT(op == Token::ADD || | 884 ASSERT(op == Token::ADD || |
| 856 op == Token::DIV || | 885 op == Token::DIV || |
| 857 op == Token::MOD || | 886 op == Token::MOD || |
| 858 op == Token::MUL || | 887 op == Token::MUL || |
| 859 op == Token::SUB); | 888 op == Token::SUB); |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1068 HIsObject* compare = HIsObject::cast(v); | 1097 HIsObject* compare = HIsObject::cast(v); |
| 1069 ASSERT(compare->value()->representation().IsTagged()); | 1098 ASSERT(compare->value()->representation().IsTagged()); |
| 1070 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value())); | 1099 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value())); |
| 1071 } else if (v->IsCompareJSObjectEq()) { | 1100 } else if (v->IsCompareJSObjectEq()) { |
| 1072 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v); | 1101 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v); |
| 1073 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()), | 1102 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()), |
| 1074 UseRegisterAtStart(compare->right())); | 1103 UseRegisterAtStart(compare->right())); |
| 1075 } else if (v->IsInstanceOf()) { | 1104 } else if (v->IsInstanceOf()) { |
| 1076 HInstanceOf* instance_of = HInstanceOf::cast(v); | 1105 HInstanceOf* instance_of = HInstanceOf::cast(v); |
| 1077 LInstanceOfAndBranch* result = | 1106 LInstanceOfAndBranch* result = |
| 1078 new LInstanceOfAndBranch( | 1107 new LInstanceOfAndBranch(UseFixed(instance_of->left(), rax), |
| 1079 UseFixed(instance_of->left(), InstanceofStub::left()), | 1108 UseFixed(instance_of->right(), rdx)); |
| 1080 UseFixed(instance_of->right(), InstanceofStub::right())); | |
| 1081 return MarkAsCall(result, instr); | 1109 return MarkAsCall(result, instr); |
| 1082 } else if (v->IsTypeofIs()) { | 1110 } else if (v->IsTypeofIs()) { |
| 1083 HTypeofIs* typeof_is = HTypeofIs::cast(v); | 1111 HTypeofIs* typeof_is = HTypeofIs::cast(v); |
| 1084 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value())); | 1112 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value())); |
| 1085 } else if (v->IsIsConstructCall()) { | 1113 } else if (v->IsIsConstructCall()) { |
| 1086 return new LIsConstructCallAndBranch(TempRegister()); | 1114 return new LIsConstructCallAndBranch(TempRegister()); |
| 1087 } else { | 1115 } else { |
| 1088 if (v->IsConstant()) { | 1116 if (v->IsConstant()) { |
| 1089 if (HConstant::cast(v)->handle()->IsTrue()) { | 1117 if (HConstant::cast(v)->handle()->IsTrue()) { |
| 1090 return new LGoto(instr->FirstSuccessor()->block_id()); | 1118 return new LGoto(instr->FirstSuccessor()->block_id()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1101 | 1129 |
| 1102 | 1130 |
| 1103 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { | 1131 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { |
| 1104 ASSERT(instr->value()->representation().IsTagged()); | 1132 ASSERT(instr->value()->representation().IsTagged()); |
| 1105 LOperand* value = UseRegisterAtStart(instr->value()); | 1133 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1106 return new LCmpMapAndBranch(value); | 1134 return new LCmpMapAndBranch(value); |
| 1107 } | 1135 } |
| 1108 | 1136 |
| 1109 | 1137 |
| 1110 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { | 1138 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { |
| 1111 Abort("Unimplemented: %s", "DoArgumentsLength"); | 1139 return DefineAsRegister(new LArgumentsLength(Use(length->value()))); |
| 1112 return NULL; | |
| 1113 } | 1140 } |
| 1114 | 1141 |
| 1115 | 1142 |
| 1116 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { | 1143 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { |
| 1117 Abort("Unimplemented: %s", "DoArgumentsElements"); | 1144 return DefineAsRegister(new LArgumentsElements); |
| 1118 return NULL; | |
| 1119 } | 1145 } |
| 1120 | 1146 |
| 1121 | 1147 |
| 1122 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { | 1148 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { |
| 1123 Abort("Unimplemented: %s", "DoInstanceOf"); | 1149 LOperand* left = UseFixed(instr->left(), rax); |
| 1124 return NULL; | 1150 LOperand* right = UseFixed(instr->right(), rdx); |
| 1151 LInstanceOf* result = new LInstanceOf(left, right); |
| 1152 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1125 } | 1153 } |
| 1126 | 1154 |
| 1127 | 1155 |
| 1128 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( | 1156 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( |
| 1129 HInstanceOfKnownGlobal* instr) { | 1157 HInstanceOfKnownGlobal* instr) { |
| 1130 Abort("Unimplemented: %s", "DoInstanceOfKnownGlobal"); | 1158 LInstanceOfKnownGlobal* result = |
| 1131 return NULL; | 1159 new LInstanceOfKnownGlobal(UseFixed(instr->value(), rax)); |
| 1160 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1132 } | 1161 } |
| 1133 | 1162 |
| 1134 | 1163 |
| 1135 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { | 1164 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { |
| 1136 Abort("Unimplemented: %s", "DoApplyArguments"); | 1165 LOperand* function = UseFixed(instr->function(), rdi); |
| 1137 return NULL; | 1166 LOperand* receiver = UseFixed(instr->receiver(), rax); |
| 1167 LOperand* length = UseFixed(instr->length(), rbx); |
| 1168 LOperand* elements = UseFixed(instr->elements(), rcx); |
| 1169 LApplyArguments* result = new LApplyArguments(function, |
| 1170 receiver, |
| 1171 length, |
| 1172 elements); |
| 1173 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY); |
| 1138 } | 1174 } |
| 1139 | 1175 |
| 1140 | 1176 |
| 1141 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { | 1177 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { |
| 1142 ++argument_count_; | 1178 ++argument_count_; |
| 1143 LOperand* argument = UseOrConstant(instr->argument()); | 1179 LOperand* argument = UseOrConstant(instr->argument()); |
| 1144 return new LPushArgument(argument); | 1180 return new LPushArgument(argument); |
| 1145 } | 1181 } |
| 1146 | 1182 |
| 1147 | 1183 |
| 1148 LInstruction* LChunkBuilder::DoContext(HContext* instr) { | 1184 LInstruction* LChunkBuilder::DoContext(HContext* instr) { |
| 1149 Abort("Unimplemented: DoContext"); | 1185 return DefineAsRegister(new LContext); |
| 1150 return NULL; | |
| 1151 } | 1186 } |
| 1152 | 1187 |
| 1153 | 1188 |
| 1154 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { | 1189 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { |
| 1155 Abort("Unimplemented: DoOuterContext"); | 1190 LOperand* context = UseRegisterAtStart(instr->value()); |
| 1156 return NULL; | 1191 return DefineAsRegister(new LOuterContext(context)); |
| 1157 } | 1192 } |
| 1158 | 1193 |
| 1159 | 1194 |
| 1160 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { | 1195 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { |
| 1161 return DefineAsRegister(new LGlobalObject); | 1196 return DefineAsRegister(new LGlobalObject); |
| 1162 } | 1197 } |
| 1163 | 1198 |
| 1164 | 1199 |
| 1165 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) { | 1200 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) { |
| 1166 return DefineAsRegister(new LGlobalReceiver); | 1201 return DefineAsRegister(new LGlobalReceiver); |
| 1167 } | 1202 } |
| 1168 | 1203 |
| 1169 | 1204 |
| 1170 LInstruction* LChunkBuilder::DoCallConstantFunction( | 1205 LInstruction* LChunkBuilder::DoCallConstantFunction( |
| 1171 HCallConstantFunction* instr) { | 1206 HCallConstantFunction* instr) { |
| 1172 argument_count_ -= instr->argument_count(); | 1207 argument_count_ -= instr->argument_count(); |
| 1173 return MarkAsCall(DefineFixed(new LCallConstantFunction, rax), instr); | 1208 return MarkAsCall(DefineFixed(new LCallConstantFunction, rax), instr); |
| 1174 } | 1209 } |
| 1175 | 1210 |
| 1176 | 1211 |
| 1177 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { | 1212 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { |
| 1178 Abort("Unimplemented: %s", "DoUnaryMathOperation"); | 1213 BuiltinFunctionId op = instr->op(); |
| 1179 return NULL; | 1214 if (op == kMathLog || op == kMathSin || op == kMathCos) { |
| 1215 LOperand* input = UseFixedDouble(instr->value(), xmm1); |
| 1216 LUnaryMathOperation* result = new LUnaryMathOperation(input); |
| 1217 return MarkAsCall(DefineFixedDouble(result, xmm1), instr); |
| 1218 } else { |
| 1219 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1220 LUnaryMathOperation* result = new LUnaryMathOperation(input); |
| 1221 switch (op) { |
| 1222 case kMathAbs: |
| 1223 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| 1224 case kMathFloor: |
| 1225 return AssignEnvironment(DefineAsRegister(result)); |
| 1226 case kMathRound: |
| 1227 return AssignEnvironment(DefineAsRegister(result)); |
| 1228 case kMathSqrt: |
| 1229 return DefineSameAsFirst(result); |
| 1230 case kMathPowHalf: |
| 1231 return DefineSameAsFirst(result); |
| 1232 default: |
| 1233 UNREACHABLE(); |
| 1234 return NULL; |
| 1235 } |
| 1236 } |
| 1180 } | 1237 } |
| 1181 | 1238 |
| 1182 | 1239 |
| 1183 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { | 1240 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { |
| 1184 Abort("Unimplemented: %s", "DoCallKeyed"); | 1241 ASSERT(instr->key()->representation().IsTagged()); |
| 1185 return NULL; | 1242 LOperand* key = UseFixed(instr->key(), rcx); |
| 1243 argument_count_ -= instr->argument_count(); |
| 1244 LCallKeyed* result = new LCallKeyed(key); |
| 1245 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1186 } | 1246 } |
| 1187 | 1247 |
| 1188 | 1248 |
| 1189 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { | 1249 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { |
| 1190 argument_count_ -= instr->argument_count(); | 1250 argument_count_ -= instr->argument_count(); |
| 1191 return MarkAsCall(DefineFixed(new LCallNamed, rax), instr); | 1251 return MarkAsCall(DefineFixed(new LCallNamed, rax), instr); |
| 1192 } | 1252 } |
| 1193 | 1253 |
| 1194 | 1254 |
| 1195 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { | 1255 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { |
| 1196 Abort("Unimplemented: %s", "DoCallGlobal"); | 1256 argument_count_ -= instr->argument_count(); |
| 1197 return NULL; | 1257 return MarkAsCall(DefineFixed(new LCallGlobal, rax), instr); |
| 1198 } | 1258 } |
| 1199 | 1259 |
| 1200 | 1260 |
| 1201 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { | 1261 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { |
| 1202 argument_count_ -= instr->argument_count(); | 1262 argument_count_ -= instr->argument_count(); |
| 1203 return MarkAsCall(DefineFixed(new LCallKnownGlobal, rax), instr); | 1263 return MarkAsCall(DefineFixed(new LCallKnownGlobal, rax), instr); |
| 1204 } | 1264 } |
| 1205 | 1265 |
| 1206 | 1266 |
| 1207 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { | 1267 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { |
| 1208 LOperand* constructor = UseFixed(instr->constructor(), rdi); | 1268 LOperand* constructor = UseFixed(instr->constructor(), rdi); |
| 1209 argument_count_ -= instr->argument_count(); | 1269 argument_count_ -= instr->argument_count(); |
| 1210 LCallNew* result = new LCallNew(constructor); | 1270 LCallNew* result = new LCallNew(constructor); |
| 1211 return MarkAsCall(DefineFixed(result, rax), instr); | 1271 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1212 } | 1272 } |
| 1213 | 1273 |
| 1214 | 1274 |
| 1215 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { | 1275 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { |
| 1216 Abort("Unimplemented: %s", "DoCallFunction"); | 1276 argument_count_ -= instr->argument_count(); |
| 1217 return NULL; | 1277 LCallFunction* result = new LCallFunction(); |
| 1278 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1218 } | 1279 } |
| 1219 | 1280 |
| 1220 | 1281 |
| 1221 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { | 1282 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { |
| 1222 argument_count_ -= instr->argument_count(); | 1283 argument_count_ -= instr->argument_count(); |
| 1223 return MarkAsCall(DefineFixed(new LCallRuntime, rax), instr); | 1284 return MarkAsCall(DefineFixed(new LCallRuntime, rax), instr); |
| 1224 } | 1285 } |
| 1225 | 1286 |
| 1226 | 1287 |
| 1227 LInstruction* LChunkBuilder::DoShr(HShr* instr) { | 1288 LInstruction* LChunkBuilder::DoShr(HShr* instr) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1275 LDivI* result = new LDivI(dividend, divisor, temp); | 1336 LDivI* result = new LDivI(dividend, divisor, temp); |
| 1276 return AssignEnvironment(DefineFixed(result, rax)); | 1337 return AssignEnvironment(DefineFixed(result, rax)); |
| 1277 } else { | 1338 } else { |
| 1278 ASSERT(instr->representation().IsTagged()); | 1339 ASSERT(instr->representation().IsTagged()); |
| 1279 return DoArithmeticT(Token::DIV, instr); | 1340 return DoArithmeticT(Token::DIV, instr); |
| 1280 } | 1341 } |
| 1281 } | 1342 } |
| 1282 | 1343 |
| 1283 | 1344 |
| 1284 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1345 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1285 Abort("Unimplemented: %s", "DoMod"); | 1346 if (instr->representation().IsInteger32()) { |
| 1286 return NULL; | 1347 ASSERT(instr->left()->representation().IsInteger32()); |
| 1348 ASSERT(instr->right()->representation().IsInteger32()); |
| 1349 // The temporary operand is necessary to ensure that right is not allocated |
| 1350 // into edx. |
| 1351 LOperand* temp = FixedTemp(rdx); |
| 1352 LOperand* value = UseFixed(instr->left(), rax); |
| 1353 LOperand* divisor = UseRegister(instr->right()); |
| 1354 LModI* mod = new LModI(value, divisor, temp); |
| 1355 LInstruction* result = DefineFixed(mod, rdx); |
| 1356 return (instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
| 1357 instr->CheckFlag(HValue::kCanBeDivByZero)) |
| 1358 ? AssignEnvironment(result) |
| 1359 : result; |
| 1360 } else if (instr->representation().IsTagged()) { |
| 1361 return DoArithmeticT(Token::MOD, instr); |
| 1362 } else { |
| 1363 ASSERT(instr->representation().IsDouble()); |
| 1364 // We call a C function for double modulo. It can't trigger a GC. |
| 1365 // We need to use fixed result register for the call. |
| 1366 // TODO(fschneider): Allow any register as input registers. |
| 1367 LOperand* left = UseFixedDouble(instr->left(), xmm2); |
| 1368 LOperand* right = UseFixedDouble(instr->right(), xmm1); |
| 1369 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right); |
| 1370 return MarkAsCall(DefineFixedDouble(result, xmm1), instr); |
| 1371 } |
| 1287 } | 1372 } |
| 1288 | 1373 |
| 1289 | 1374 |
| 1290 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1375 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
| 1291 if (instr->representation().IsInteger32()) { | 1376 if (instr->representation().IsInteger32()) { |
| 1292 ASSERT(instr->left()->representation().IsInteger32()); | 1377 ASSERT(instr->left()->representation().IsInteger32()); |
| 1293 ASSERT(instr->right()->representation().IsInteger32()); | 1378 ASSERT(instr->right()->representation().IsInteger32()); |
| 1294 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); | 1379 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); |
| 1295 LOperand* right = UseOrConstant(instr->MostConstantOperand()); | 1380 LOperand* right = UseOrConstant(instr->MostConstantOperand()); |
| 1296 LMulI* mul = new LMulI(left, right); | 1381 LMulI* mul = new LMulI(left, right); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1331 ASSERT(instr->right()->representation().IsInteger32()); | 1416 ASSERT(instr->right()->representation().IsInteger32()); |
| 1332 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); | 1417 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); |
| 1333 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); | 1418 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); |
| 1334 LAddI* add = new LAddI(left, right); | 1419 LAddI* add = new LAddI(left, right); |
| 1335 LInstruction* result = DefineSameAsFirst(add); | 1420 LInstruction* result = DefineSameAsFirst(add); |
| 1336 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1421 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1337 result = AssignEnvironment(result); | 1422 result = AssignEnvironment(result); |
| 1338 } | 1423 } |
| 1339 return result; | 1424 return result; |
| 1340 } else if (instr->representation().IsDouble()) { | 1425 } else if (instr->representation().IsDouble()) { |
| 1341 Abort("Unimplemented: %s", "DoAdd on Doubles"); | 1426 return DoArithmeticD(Token::ADD, instr); |
| 1342 } else { | 1427 } else { |
| 1343 ASSERT(instr->representation().IsTagged()); | 1428 ASSERT(instr->representation().IsTagged()); |
| 1344 return DoArithmeticT(Token::ADD, instr); | 1429 return DoArithmeticT(Token::ADD, instr); |
| 1345 } | 1430 } |
| 1346 return NULL; | 1431 return NULL; |
| 1347 } | 1432 } |
| 1348 | 1433 |
| 1349 | 1434 |
| 1350 LInstruction* LChunkBuilder::DoPower(HPower* instr) { | 1435 LInstruction* LChunkBuilder::DoPower(HPower* instr) { |
| 1351 Abort("Unimplemented: %s", "DoPower"); | 1436 ASSERT(instr->representation().IsDouble()); |
| 1352 return NULL; | 1437 // We call a C function for double power. It can't trigger a GC. |
| 1438 // We need to use fixed result register for the call. |
| 1439 Representation exponent_type = instr->right()->representation(); |
| 1440 ASSERT(instr->left()->representation().IsDouble()); |
| 1441 LOperand* left = UseFixedDouble(instr->left(), xmm2); |
| 1442 LOperand* right = exponent_type.IsDouble() ? |
| 1443 UseFixedDouble(instr->right(), xmm1) : |
| 1444 #ifdef _WIN64 |
| 1445 UseFixed(instr->right(), rdx); |
| 1446 #else |
| 1447 UseFixed(instr->right(), rdi); |
| 1448 #endif |
| 1449 LPower* result = new LPower(left, right); |
| 1450 return MarkAsCall(DefineFixedDouble(result, xmm1), instr, |
| 1451 CAN_DEOPTIMIZE_EAGERLY); |
| 1353 } | 1452 } |
| 1354 | 1453 |
| 1355 | 1454 |
| 1356 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { | 1455 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { |
| 1357 Token::Value op = instr->token(); | 1456 Token::Value op = instr->token(); |
| 1358 Representation r = instr->GetInputRepresentation(); | 1457 Representation r = instr->GetInputRepresentation(); |
| 1359 if (r.IsInteger32()) { | 1458 if (r.IsInteger32()) { |
| 1360 ASSERT(instr->left()->representation().IsInteger32()); | 1459 ASSERT(instr->left()->representation().IsInteger32()); |
| 1361 ASSERT(instr->right()->representation().IsInteger32()); | 1460 ASSERT(instr->right()->representation().IsInteger32()); |
| 1362 LOperand* left = UseRegisterAtStart(instr->left()); | 1461 LOperand* left = UseRegisterAtStart(instr->left()); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1407 | 1506 |
| 1408 LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) { | 1507 LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) { |
| 1409 ASSERT(instr->value()->representation().IsTagged()); | 1508 ASSERT(instr->value()->representation().IsTagged()); |
| 1410 LOperand* value = UseAtStart(instr->value()); | 1509 LOperand* value = UseAtStart(instr->value()); |
| 1411 | 1510 |
| 1412 return DefineAsRegister(new LIsSmi(value)); | 1511 return DefineAsRegister(new LIsSmi(value)); |
| 1413 } | 1512 } |
| 1414 | 1513 |
| 1415 | 1514 |
| 1416 LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) { | 1515 LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) { |
| 1417 Abort("Unimplemented: %s", "DoHasInstanceType"); | 1516 ASSERT(instr->value()->representation().IsTagged()); |
| 1517 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1518 |
| 1519 return DefineAsRegister(new LHasInstanceType(value)); |
| 1520 } |
| 1521 |
| 1522 |
| 1523 LInstruction* LChunkBuilder::DoGetCachedArrayIndex( |
| 1524 HGetCachedArrayIndex* instr) { |
| 1525 Abort("Unimplemented: %s", "DoGetCachedArrayIndex"); |
| 1418 return NULL; | 1526 return NULL; |
| 1419 } | 1527 } |
| 1420 | 1528 |
| 1421 | 1529 |
| 1422 LInstruction* LChunkBuilder::DoHasCachedArrayIndex( | 1530 LInstruction* LChunkBuilder::DoHasCachedArrayIndex( |
| 1423 HHasCachedArrayIndex* instr) { | 1531 HHasCachedArrayIndex* instr) { |
| 1424 Abort("Unimplemented: %s", "DoHasCachedArrayIndex"); | 1532 ASSERT(instr->value()->representation().IsTagged()); |
| 1425 return NULL; | 1533 LOperand* value = UseRegister(instr->value()); |
| 1534 return DefineAsRegister(new LHasCachedArrayIndex(value)); |
| 1426 } | 1535 } |
| 1427 | 1536 |
| 1428 | 1537 |
| 1429 LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) { | 1538 LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) { |
| 1430 Abort("Unimplemented: %s", "DoClassOfTest"); | 1539 Abort("Unimplemented: %s", "DoClassOfTest"); |
| 1431 return NULL; | 1540 return NULL; |
| 1432 } | 1541 } |
| 1433 | 1542 |
| 1434 | 1543 |
| 1435 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) { | 1544 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) { |
| 1436 LOperand* array = UseRegisterAtStart(instr->value()); | 1545 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1437 return DefineAsRegister(new LJSArrayLength(array)); | 1546 return DefineAsRegister(new LJSArrayLength(array)); |
| 1438 } | 1547 } |
| 1439 | 1548 |
| 1440 | 1549 |
| 1441 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) { | 1550 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) { |
| 1442 LOperand* array = UseRegisterAtStart(instr->value()); | 1551 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1443 return DefineAsRegister(new LFixedArrayLength(array)); | 1552 return DefineAsRegister(new LFixedArrayLength(array)); |
| 1444 } | 1553 } |
| 1445 | 1554 |
| 1446 | 1555 |
| 1556 LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) { |
| 1557 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1558 return DefineAsRegister(new LPixelArrayLength(array)); |
| 1559 } |
| 1560 |
| 1561 |
| 1447 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { | 1562 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { |
| 1448 Abort("Unimplemented: %s", "DoValueOf"); | 1563 LOperand* object = UseRegister(instr->value()); |
| 1449 return NULL; | 1564 LValueOf* result = new LValueOf(object); |
| 1565 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1450 } | 1566 } |
| 1451 | 1567 |
| 1452 | 1568 |
| 1453 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { | 1569 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { |
| 1454 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), | 1570 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), |
| 1455 Use(instr->length()))); | 1571 Use(instr->length()))); |
| 1456 } | 1572 } |
| 1457 | 1573 |
| 1458 | 1574 |
| 1459 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { | 1575 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1497 if (to.IsTagged()) { | 1613 if (to.IsTagged()) { |
| 1498 LOperand* value = UseRegister(instr->value()); | 1614 LOperand* value = UseRegister(instr->value()); |
| 1499 LOperand* temp = TempRegister(); | 1615 LOperand* temp = TempRegister(); |
| 1500 | 1616 |
| 1501 // Make sure that temp and result_temp are different registers. | 1617 // Make sure that temp and result_temp are different registers. |
| 1502 LUnallocated* result_temp = TempRegister(); | 1618 LUnallocated* result_temp = TempRegister(); |
| 1503 LNumberTagD* result = new LNumberTagD(value, temp); | 1619 LNumberTagD* result = new LNumberTagD(value, temp); |
| 1504 return AssignPointerMap(Define(result, result_temp)); | 1620 return AssignPointerMap(Define(result, result_temp)); |
| 1505 } else { | 1621 } else { |
| 1506 ASSERT(to.IsInteger32()); | 1622 ASSERT(to.IsInteger32()); |
| 1507 bool needs_temp = instr->CanTruncateToInt32() && | 1623 LOperand* value = UseRegister(instr->value()); |
| 1508 !Isolate::Current()->cpu_features()->IsSupported(SSE3); | 1624 return AssignEnvironment(DefineAsRegister(new LDoubleToI(value))); |
| 1509 LOperand* value = needs_temp ? | |
| 1510 UseTempRegister(instr->value()) : UseRegister(instr->value()); | |
| 1511 LOperand* temp = needs_temp ? TempRegister() : NULL; | |
| 1512 return AssignEnvironment(DefineAsRegister(new LDoubleToI(value, temp))); | |
| 1513 } | 1625 } |
| 1514 } else if (from.IsInteger32()) { | 1626 } else if (from.IsInteger32()) { |
| 1515 if (to.IsTagged()) { | 1627 if (to.IsTagged()) { |
| 1516 HValue* val = instr->value(); | 1628 HValue* val = instr->value(); |
| 1517 LOperand* value = UseRegister(val); | 1629 LOperand* value = UseRegister(val); |
| 1518 if (val->HasRange() && val->range()->IsInSmiRange()) { | 1630 if (val->HasRange() && val->range()->IsInSmiRange()) { |
| 1519 return DefineSameAsFirst(new LSmiTag(value)); | 1631 return DefineSameAsFirst(new LSmiTag(value)); |
| 1520 } else { | 1632 } else { |
| 1521 LNumberTagI* result = new LNumberTagI(value); | 1633 LNumberTagI* result = new LNumberTagI(value); |
| 1522 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 1634 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1600 | 1712 |
| 1601 | 1713 |
| 1602 LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) { | 1714 LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) { |
| 1603 LStoreGlobal* result = new LStoreGlobal(UseRegister(instr->value()), | 1715 LStoreGlobal* result = new LStoreGlobal(UseRegister(instr->value()), |
| 1604 TempRegister()); | 1716 TempRegister()); |
| 1605 return instr->check_hole_value() ? AssignEnvironment(result) : result; | 1717 return instr->check_hole_value() ? AssignEnvironment(result) : result; |
| 1606 } | 1718 } |
| 1607 | 1719 |
| 1608 | 1720 |
| 1609 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { | 1721 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { |
| 1610 Abort("Unimplemented: %s", "DoLoadContextSlot"); | 1722 LOperand* context = UseRegisterAtStart(instr->value()); |
| 1611 return NULL; | 1723 return DefineAsRegister(new LLoadContextSlot(context)); |
| 1612 } | 1724 } |
| 1613 | 1725 |
| 1614 | 1726 |
| 1615 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { | 1727 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { |
| 1616 Abort("Unimplemented: DoStoreContextSlot"); | 1728 Abort("Unimplemented: DoStoreContextSlot"); // Temporarily disabled (whesse). |
| 1617 return NULL; | 1729 LOperand* context; |
| 1730 LOperand* value; |
| 1731 if (instr->NeedsWriteBarrier()) { |
| 1732 context = UseTempRegister(instr->context()); |
| 1733 value = UseTempRegister(instr->value()); |
| 1734 } else { |
| 1735 context = UseRegister(instr->context()); |
| 1736 value = UseRegister(instr->value()); |
| 1737 } |
| 1738 return new LStoreContextSlot(context, value); |
| 1618 } | 1739 } |
| 1619 | 1740 |
| 1620 | 1741 |
| 1621 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { | 1742 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { |
| 1622 ASSERT(instr->representation().IsTagged()); | 1743 ASSERT(instr->representation().IsTagged()); |
| 1623 LOperand* obj = UseRegisterAtStart(instr->object()); | 1744 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 1624 return DefineAsRegister(new LLoadNamedField(obj)); | 1745 return DefineAsRegister(new LLoadNamedField(obj)); |
| 1625 } | 1746 } |
| 1626 | 1747 |
| 1627 | 1748 |
| 1628 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { | 1749 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { |
| 1629 LOperand* object = UseFixed(instr->object(), rax); | 1750 LOperand* object = UseFixed(instr->object(), rax); |
| 1630 LLoadNamedGeneric* result = new LLoadNamedGeneric(object); | 1751 LLoadNamedGeneric* result = new LLoadNamedGeneric(object); |
| 1631 return MarkAsCall(DefineFixed(result, rax), instr); | 1752 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1632 } | 1753 } |
| 1633 | 1754 |
| 1634 | 1755 |
| 1635 LInstruction* LChunkBuilder::DoLoadFunctionPrototype( | 1756 LInstruction* LChunkBuilder::DoLoadFunctionPrototype( |
| 1636 HLoadFunctionPrototype* instr) { | 1757 HLoadFunctionPrototype* instr) { |
| 1637 Abort("Unimplemented: %s", "DoLoadFunctionPrototype"); | 1758 return AssignEnvironment(DefineAsRegister( |
| 1638 return NULL; | 1759 new LLoadFunctionPrototype(UseRegister(instr->function())))); |
| 1639 } | 1760 } |
| 1640 | 1761 |
| 1641 | 1762 |
| 1642 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) { | 1763 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) { |
| 1643 LOperand* input = UseRegisterAtStart(instr->value()); | 1764 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1644 return DefineSameAsFirst(new LLoadElements(input)); | 1765 return DefineAsRegister(new LLoadElements(input)); |
| 1766 } |
| 1767 |
| 1768 |
| 1769 LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer( |
| 1770 HLoadPixelArrayExternalPointer* instr) { |
| 1771 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1772 return DefineAsRegister(new LLoadPixelArrayExternalPointer(input)); |
| 1645 } | 1773 } |
| 1646 | 1774 |
| 1647 | 1775 |
| 1648 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( | 1776 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( |
| 1649 HLoadKeyedFastElement* instr) { | 1777 HLoadKeyedFastElement* instr) { |
| 1650 ASSERT(instr->representation().IsTagged()); | 1778 ASSERT(instr->representation().IsTagged()); |
| 1651 ASSERT(instr->key()->representation().IsInteger32()); | 1779 ASSERT(instr->key()->representation().IsInteger32()); |
| 1652 LOperand* obj = UseRegisterAtStart(instr->object()); | 1780 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 1653 LOperand* key = UseRegisterAtStart(instr->key()); | 1781 LOperand* key = UseRegisterAtStart(instr->key()); |
| 1654 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); | 1782 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); |
| 1655 return AssignEnvironment(DefineSameAsFirst(result)); | 1783 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1656 } | 1784 } |
| 1657 | 1785 |
| 1658 | 1786 |
| 1787 LInstruction* LChunkBuilder::DoLoadPixelArrayElement( |
| 1788 HLoadPixelArrayElement* instr) { |
| 1789 ASSERT(instr->representation().IsInteger32()); |
| 1790 ASSERT(instr->key()->representation().IsInteger32()); |
| 1791 LOperand* external_pointer = |
| 1792 UseRegisterAtStart(instr->external_pointer()); |
| 1793 LOperand* key = UseRegisterAtStart(instr->key()); |
| 1794 LLoadPixelArrayElement* result = |
| 1795 new LLoadPixelArrayElement(external_pointer, key); |
| 1796 return DefineSameAsFirst(result); |
| 1797 } |
| 1798 |
| 1799 |
| 1659 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 1800 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
| 1660 Abort("Unimplemented: %s", "DoLoadKeyedGeneric"); | 1801 LOperand* object = UseFixed(instr->object(), rdx); |
| 1661 return NULL; | 1802 LOperand* key = UseFixed(instr->key(), rax); |
| 1803 |
| 1804 LLoadKeyedGeneric* result = new LLoadKeyedGeneric(object, key); |
| 1805 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1662 } | 1806 } |
| 1663 | 1807 |
| 1664 | 1808 |
| 1665 LInstruction* LChunkBuilder::DoStoreKeyedFastElement( | 1809 LInstruction* LChunkBuilder::DoStoreKeyedFastElement( |
| 1666 HStoreKeyedFastElement* instr) { | 1810 HStoreKeyedFastElement* instr) { |
| 1667 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 1811 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
| 1668 ASSERT(instr->value()->representation().IsTagged()); | 1812 ASSERT(instr->value()->representation().IsTagged()); |
| 1669 ASSERT(instr->object()->representation().IsTagged()); | 1813 ASSERT(instr->object()->representation().IsTagged()); |
| 1670 ASSERT(instr->key()->representation().IsInteger32()); | 1814 ASSERT(instr->key()->representation().IsInteger32()); |
| 1671 | 1815 |
| 1672 LOperand* obj = UseTempRegister(instr->object()); | 1816 LOperand* obj = UseTempRegister(instr->object()); |
| 1673 LOperand* val = needs_write_barrier | 1817 LOperand* val = needs_write_barrier |
| 1674 ? UseTempRegister(instr->value()) | 1818 ? UseTempRegister(instr->value()) |
| 1675 : UseRegisterAtStart(instr->value()); | 1819 : UseRegisterAtStart(instr->value()); |
| 1676 LOperand* key = needs_write_barrier | 1820 LOperand* key = needs_write_barrier |
| 1677 ? UseTempRegister(instr->key()) | 1821 ? UseTempRegister(instr->key()) |
| 1678 : UseRegisterOrConstantAtStart(instr->key()); | 1822 : UseRegisterOrConstantAtStart(instr->key()); |
| 1679 | 1823 |
| 1680 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); | 1824 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); |
| 1681 } | 1825 } |
| 1682 | 1826 |
| 1683 | 1827 |
| 1828 LInstruction* LChunkBuilder::DoStorePixelArrayElement( |
| 1829 HStorePixelArrayElement* instr) { |
| 1830 ASSERT(instr->value()->representation().IsInteger32()); |
| 1831 ASSERT(instr->external_pointer()->representation().IsExternal()); |
| 1832 ASSERT(instr->key()->representation().IsInteger32()); |
| 1833 |
| 1834 LOperand* external_pointer = UseRegister(instr->external_pointer()); |
| 1835 LOperand* val = UseTempRegister(instr->value()); |
| 1836 LOperand* key = UseRegister(instr->key()); |
| 1837 |
| 1838 return new LStorePixelArrayElement(external_pointer, key, val); |
| 1839 } |
| 1840 |
| 1841 |
| 1684 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { | 1842 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { |
| 1685 Abort("Unimplemented: %s", "DoStoreKeyedGeneric"); | 1843 LOperand* object = UseFixed(instr->object(), rdx); |
| 1686 return NULL; | 1844 LOperand* key = UseFixed(instr->key(), rcx); |
| 1845 LOperand* value = UseFixed(instr->value(), rax); |
| 1846 |
| 1847 ASSERT(instr->object()->representation().IsTagged()); |
| 1848 ASSERT(instr->key()->representation().IsTagged()); |
| 1849 ASSERT(instr->value()->representation().IsTagged()); |
| 1850 |
| 1851 LStoreKeyedGeneric* result = new LStoreKeyedGeneric(object, key, value); |
| 1852 return MarkAsCall(result, instr); |
| 1687 } | 1853 } |
| 1688 | 1854 |
| 1689 | 1855 |
| 1690 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { | 1856 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { |
| 1691 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 1857 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
| 1692 | 1858 |
| 1693 LOperand* obj = needs_write_barrier | 1859 LOperand* obj = needs_write_barrier |
| 1694 ? UseTempRegister(instr->object()) | 1860 ? UseTempRegister(instr->object()) |
| 1695 : UseRegisterAtStart(instr->object()); | 1861 : UseRegisterAtStart(instr->object()); |
| 1696 | 1862 |
| 1697 LOperand* val = needs_write_barrier | 1863 LOperand* val = needs_write_barrier |
| 1698 ? UseTempRegister(instr->value()) | 1864 ? UseTempRegister(instr->value()) |
| 1699 : UseRegister(instr->value()); | 1865 : UseRegister(instr->value()); |
| 1700 | 1866 |
| 1701 // We only need a scratch register if we have a write barrier or we | 1867 // We only need a scratch register if we have a write barrier or we |
| 1702 // have a store into the properties array (not in-object-property). | 1868 // have a store into the properties array (not in-object-property). |
| 1703 LOperand* temp = (!instr->is_in_object() || needs_write_barrier) | 1869 LOperand* temp = (!instr->is_in_object() || needs_write_barrier) |
| 1704 ? TempRegister() : NULL; | 1870 ? TempRegister() : NULL; |
| 1705 | 1871 |
| 1706 return new LStoreNamedField(obj, val, temp); | 1872 return new LStoreNamedField(obj, val, temp); |
| 1707 } | 1873 } |
| 1708 | 1874 |
| 1709 | 1875 |
| 1710 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { | 1876 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { |
| 1711 Abort("Unimplemented: %s", "DoStoreNamedGeneric"); | 1877 LOperand* object = UseFixed(instr->object(), rdx); |
| 1712 return NULL; | 1878 LOperand* value = UseFixed(instr->value(), rax); |
| 1879 |
| 1880 LStoreNamedGeneric* result = new LStoreNamedGeneric(object, value); |
| 1881 return MarkAsCall(result, instr); |
| 1713 } | 1882 } |
| 1714 | 1883 |
| 1715 | 1884 |
| 1716 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { | 1885 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { |
| 1717 Abort("Unimplemented: %s", "DoStringCharCodeAt"); | 1886 LOperand* string = UseRegister(instr->string()); |
| 1718 return NULL; | 1887 LOperand* index = UseRegisterOrConstant(instr->index()); |
| 1888 LStringCharCodeAt* result = new LStringCharCodeAt(string, index); |
| 1889 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
| 1719 } | 1890 } |
| 1720 | 1891 |
| 1721 | 1892 |
| 1722 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) { | 1893 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) { |
| 1723 Abort("Unimplemented: %s", "DoStringLength"); | 1894 LOperand* string = UseRegisterAtStart(instr->value()); |
| 1724 return NULL; | 1895 return DefineAsRegister(new LStringLength(string)); |
| 1725 } | 1896 } |
| 1726 | 1897 |
| 1727 | 1898 |
| 1728 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { | 1899 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { |
| 1729 return MarkAsCall(DefineFixed(new LArrayLiteral, rax), instr); | 1900 return MarkAsCall(DefineFixed(new LArrayLiteral, rax), instr); |
| 1730 } | 1901 } |
| 1731 | 1902 |
| 1732 | 1903 |
| 1733 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) { | 1904 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) { |
| 1734 return MarkAsCall(DefineFixed(new LObjectLiteral, rax), instr); | 1905 return MarkAsCall(DefineFixed(new LObjectLiteral, rax), instr); |
| 1735 } | 1906 } |
| 1736 | 1907 |
| 1737 | 1908 |
| 1738 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) { | 1909 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) { |
| 1739 Abort("Unimplemented: %s", "DoRegExpLiteral"); | 1910 return MarkAsCall(DefineFixed(new LRegExpLiteral, rax), instr); |
| 1740 return NULL; | |
| 1741 } | 1911 } |
| 1742 | 1912 |
| 1743 | 1913 |
| 1744 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { | 1914 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { |
| 1745 return MarkAsCall(DefineFixed(new LFunctionLiteral, rax), instr); | 1915 return MarkAsCall(DefineFixed(new LFunctionLiteral, rax), instr); |
| 1746 } | 1916 } |
| 1747 | 1917 |
| 1748 | 1918 |
| 1749 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) { | 1919 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) { |
| 1750 Abort("Unimplemented: %s", "DoDeleteProperty"); | 1920 LDeleteProperty* result = |
| 1751 return NULL; | 1921 new LDeleteProperty(Use(instr->object()), UseOrConstant(instr->key())); |
| 1922 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1752 } | 1923 } |
| 1753 | 1924 |
| 1754 | 1925 |
| 1755 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { | 1926 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { |
| 1756 Abort("Unimplemented: %s", "DoOsrEntry"); | 1927 allocator_->MarkAsOsrEntry(); |
| 1757 return NULL; | 1928 current_block_->last_environment()->set_ast_id(instr->ast_id()); |
| 1929 return AssignEnvironment(new LOsrEntry); |
| 1758 } | 1930 } |
| 1759 | 1931 |
| 1760 | 1932 |
| 1761 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { | 1933 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { |
| 1762 int spill_index = chunk()->GetParameterStackSlot(instr->index()); | 1934 int spill_index = chunk()->GetParameterStackSlot(instr->index()); |
| 1763 return DefineAsSpilled(new LParameter, spill_index); | 1935 return DefineAsSpilled(new LParameter, spill_index); |
| 1764 } | 1936 } |
| 1765 | 1937 |
| 1766 | 1938 |
| 1767 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { | 1939 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { |
| 1768 Abort("Unimplemented: %s", "DoUnknownOSRValue"); | 1940 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width. |
| 1769 return NULL; | 1941 return DefineAsSpilled(new LUnknownOSRValue, spill_index); |
| 1770 } | 1942 } |
| 1771 | 1943 |
| 1772 | 1944 |
| 1773 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { | 1945 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { |
| 1774 argument_count_ -= instr->argument_count(); | 1946 argument_count_ -= instr->argument_count(); |
| 1775 return MarkAsCall(DefineFixed(new LCallStub, rax), instr); | 1947 return MarkAsCall(DefineFixed(new LCallStub, rax), instr); |
| 1776 } | 1948 } |
| 1777 | 1949 |
| 1778 | 1950 |
| 1779 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { | 1951 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { |
| 1780 Abort("Unimplemented: %s", "DoArgumentsObject"); | 1952 // There are no real uses of the arguments object. |
| 1953 // arguments.length and element access are supported directly on |
| 1954 // stack arguments, and any real arguments object use causes a bailout. |
| 1955 // So this value is never used. |
| 1781 return NULL; | 1956 return NULL; |
| 1782 } | 1957 } |
| 1783 | 1958 |
| 1784 | 1959 |
| 1785 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { | 1960 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { |
| 1786 Abort("Unimplemented: %s", "DoAccessArgumentsAt"); | 1961 LOperand* arguments = UseRegister(instr->arguments()); |
| 1787 return NULL; | 1962 LOperand* length = UseTempRegister(instr->length()); |
| 1963 LOperand* index = Use(instr->index()); |
| 1964 LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index); |
| 1965 return AssignEnvironment(DefineAsRegister(result)); |
| 1788 } | 1966 } |
| 1789 | 1967 |
| 1790 | 1968 |
| 1791 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { | 1969 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { |
| 1792 Abort("Unimplemented: %s", "DoTypeof"); | 1970 LTypeof* result = new LTypeof(UseAtStart(instr->value())); |
| 1793 return NULL; | 1971 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1794 } | 1972 } |
| 1795 | 1973 |
| 1796 | 1974 |
| 1797 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { | 1975 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { |
| 1798 Abort("Unimplemented: %s", "DoTypeofIs"); | 1976 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); |
| 1799 return NULL; | |
| 1800 } | 1977 } |
| 1801 | 1978 |
| 1802 | 1979 |
| 1803 LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) { | 1980 LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) { |
| 1804 return DefineAsRegister(new LIsConstructCall); | 1981 return DefineAsRegister(new LIsConstructCall); |
| 1805 } | 1982 } |
| 1806 | 1983 |
| 1807 | 1984 |
| 1808 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { | 1985 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { |
| 1809 HEnvironment* env = current_block_->last_environment(); | 1986 HEnvironment* env = current_block_->last_environment(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1857 | 2034 |
| 1858 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 2035 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 1859 HEnvironment* outer = current_block_->last_environment()->outer(); | 2036 HEnvironment* outer = current_block_->last_environment()->outer(); |
| 1860 current_block_->UpdateEnvironment(outer); | 2037 current_block_->UpdateEnvironment(outer); |
| 1861 return NULL; | 2038 return NULL; |
| 1862 } | 2039 } |
| 1863 | 2040 |
| 1864 } } // namespace v8::internal | 2041 } } // namespace v8::internal |
| 1865 | 2042 |
| 1866 #endif // V8_TARGET_ARCH_X64 | 2043 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |