| 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 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 arguments()->PrintTo(stream); | 339 arguments()->PrintTo(stream); |
| 340 | 340 |
| 341 stream->Add(" length "); | 341 stream->Add(" length "); |
| 342 length()->PrintTo(stream); | 342 length()->PrintTo(stream); |
| 343 | 343 |
| 344 stream->Add(" index "); | 344 stream->Add(" index "); |
| 345 index()->PrintTo(stream); | 345 index()->PrintTo(stream); |
| 346 } | 346 } |
| 347 | 347 |
| 348 | 348 |
| 349 void LStoreNamed::PrintDataTo(StringStream* stream) { | 349 void LStoreNamedField::PrintDataTo(StringStream* stream) { |
| 350 object()->PrintTo(stream); | 350 object()->PrintTo(stream); |
| 351 stream->Add("."); | 351 stream->Add("."); |
| 352 stream->Add(*String::cast(*name())->ToCString()); | 352 stream->Add(*String::cast(*name())->ToCString()); |
| 353 stream->Add(" <- "); | 353 stream->Add(" <- "); |
| 354 value()->PrintTo(stream); | 354 value()->PrintTo(stream); |
| 355 } | 355 } |
| 356 | 356 |
| 357 | 357 |
| 358 void LStoreKeyed::PrintDataTo(StringStream* stream) { | 358 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) { |
| 359 object()->PrintTo(stream); |
| 360 stream->Add("."); |
| 361 stream->Add(*String::cast(*name())->ToCString()); |
| 362 stream->Add(" <- "); |
| 363 value()->PrintTo(stream); |
| 364 } |
| 365 |
| 366 |
| 367 void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) { |
| 359 object()->PrintTo(stream); | 368 object()->PrintTo(stream); |
| 360 stream->Add("["); | 369 stream->Add("["); |
| 361 key()->PrintTo(stream); | 370 key()->PrintTo(stream); |
| 362 stream->Add("] <- "); | 371 stream->Add("] <- "); |
| 363 value()->PrintTo(stream); | 372 value()->PrintTo(stream); |
| 364 } | 373 } |
| 365 | 374 |
| 366 | 375 |
| 367 LChunk::LChunk(HGraph* graph) | 376 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) { |
| 377 object()->PrintTo(stream); |
| 378 stream->Add("["); |
| 379 key()->PrintTo(stream); |
| 380 stream->Add("] <- "); |
| 381 value()->PrintTo(stream); |
| 382 } |
| 383 |
| 384 |
| 385 LChunk::LChunk(CompilationInfo* info, HGraph* graph) |
| 368 : spill_slot_count_(0), | 386 : spill_slot_count_(0), |
| 387 info_(info), |
| 369 graph_(graph), | 388 graph_(graph), |
| 370 instructions_(32), | 389 instructions_(32), |
| 371 pointer_maps_(8), | 390 pointer_maps_(8), |
| 372 inlined_closures_(1) { | 391 inlined_closures_(1) { |
| 373 } | 392 } |
| 374 | 393 |
| 375 | 394 |
| 376 int LChunk::GetNextSpillIndex(bool is_double) { | 395 int LChunk::GetNextSpillIndex(bool is_double) { |
| 377 // Skip a slot if for a double-width slot. | 396 // Skip a slot if for a double-width slot. |
| 378 if (is_double) spill_slot_count_++; | 397 if (is_double) spill_slot_count_++; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) { | 468 LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) { |
| 450 return LConstantOperand::Create(constant->id()); | 469 return LConstantOperand::Create(constant->id()); |
| 451 } | 470 } |
| 452 | 471 |
| 453 | 472 |
| 454 int LChunk::GetParameterStackSlot(int index) const { | 473 int LChunk::GetParameterStackSlot(int index) const { |
| 455 // The receiver is at index 0, the first parameter at index 1, so we | 474 // The receiver is at index 0, the first parameter at index 1, so we |
| 456 // shift all parameter indexes down by the number of parameters, and | 475 // shift all parameter indexes down by the number of parameters, and |
| 457 // make sure they end up negative so they are distinguishable from | 476 // make sure they end up negative so they are distinguishable from |
| 458 // spill slots. | 477 // spill slots. |
| 459 int result = index - graph()->info()->scope()->num_parameters() - 1; | 478 int result = index - info()->scope()->num_parameters() - 1; |
| 460 ASSERT(result < 0); | 479 ASSERT(result < 0); |
| 461 return result; | 480 return result; |
| 462 } | 481 } |
| 463 | 482 |
| 464 // A parameter relative to ebp in the arguments stub. | 483 // A parameter relative to ebp in the arguments stub. |
| 465 int LChunk::ParameterAt(int index) { | 484 int LChunk::ParameterAt(int index) { |
| 466 ASSERT(-1 <= index); // -1 is the receiver. | 485 ASSERT(-1 <= index); // -1 is the receiver. |
| 467 return (1 + graph()->info()->scope()->num_parameters() - index) * | 486 return (1 + info()->scope()->num_parameters() - index) * |
| 468 kPointerSize; | 487 kPointerSize; |
| 469 } | 488 } |
| 470 | 489 |
| 471 | 490 |
| 472 LGap* LChunk::GetGapAt(int index) const { | 491 LGap* LChunk::GetGapAt(int index) const { |
| 473 return LGap::cast(instructions_[index]); | 492 return LGap::cast(instructions_[index]); |
| 474 } | 493 } |
| 475 | 494 |
| 476 | 495 |
| 477 bool LChunk::IsGapAt(int index) const { | 496 bool LChunk::IsGapAt(int index) const { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 496 | 515 |
| 497 | 516 |
| 498 Representation LChunk::LookupLiteralRepresentation( | 517 Representation LChunk::LookupLiteralRepresentation( |
| 499 LConstantOperand* operand) const { | 518 LConstantOperand* operand) const { |
| 500 return graph_->LookupValue(operand->index())->representation(); | 519 return graph_->LookupValue(operand->index())->representation(); |
| 501 } | 520 } |
| 502 | 521 |
| 503 | 522 |
| 504 LChunk* LChunkBuilder::Build() { | 523 LChunk* LChunkBuilder::Build() { |
| 505 ASSERT(is_unused()); | 524 ASSERT(is_unused()); |
| 506 chunk_ = new LChunk(graph()); | 525 chunk_ = new LChunk(info(), graph()); |
| 507 HPhase phase("Building chunk", chunk_); | 526 HPhase phase("Building chunk", chunk_); |
| 508 status_ = BUILDING; | 527 status_ = BUILDING; |
| 509 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 528 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); |
| 510 for (int i = 0; i < blocks->length(); i++) { | 529 for (int i = 0; i < blocks->length(); i++) { |
| 511 HBasicBlock* next = NULL; | 530 HBasicBlock* next = NULL; |
| 512 if (i < blocks->length() - 1) next = blocks->at(i + 1); | 531 if (i < blocks->length() - 1) next = blocks->at(i + 1); |
| 513 DoBasicBlock(blocks->at(i), next); | 532 DoBasicBlock(blocks->at(i), next); |
| 514 if (is_aborted()) return NULL; | 533 if (is_aborted()) return NULL; |
| 515 } | 534 } |
| 516 status_ = DONE; | 535 status_ = DONE; |
| 517 return chunk_; | 536 return chunk_; |
| 518 } | 537 } |
| 519 | 538 |
| 520 | 539 |
| 521 void LChunkBuilder::Abort(const char* format, ...) { | 540 void LChunkBuilder::Abort(const char* format, ...) { |
| 522 if (FLAG_trace_bailout) { | 541 if (FLAG_trace_bailout) { |
| 523 SmartPointer<char> debug_name = graph()->debug_name()->ToCString(); | 542 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString()); |
| 524 PrintF("Aborting LChunk building in @\"%s\": ", *debug_name); | 543 PrintF("Aborting LChunk building in @\"%s\": ", *name); |
| 525 va_list arguments; | 544 va_list arguments; |
| 526 va_start(arguments, format); | 545 va_start(arguments, format); |
| 527 OS::VPrint(format, arguments); | 546 OS::VPrint(format, arguments); |
| 528 va_end(arguments); | 547 va_end(arguments); |
| 529 PrintF("\n"); | 548 PrintF("\n"); |
| 530 } | 549 } |
| 531 status_ = ABORTED; | 550 status_ = ABORTED; |
| 532 } | 551 } |
| 533 | 552 |
| 534 | 553 |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 if (can_deopt) AssignEnvironment(result); | 867 if (can_deopt) AssignEnvironment(result); |
| 849 return result; | 868 return result; |
| 850 } | 869 } |
| 851 | 870 |
| 852 | 871 |
| 853 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, | 872 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, |
| 854 HArithmeticBinaryOperation* instr) { | 873 HArithmeticBinaryOperation* instr) { |
| 855 ASSERT(instr->representation().IsDouble()); | 874 ASSERT(instr->representation().IsDouble()); |
| 856 ASSERT(instr->left()->representation().IsDouble()); | 875 ASSERT(instr->left()->representation().IsDouble()); |
| 857 ASSERT(instr->right()->representation().IsDouble()); | 876 ASSERT(instr->right()->representation().IsDouble()); |
| 877 ASSERT(op != Token::MOD); |
| 858 LOperand* left = UseRegisterAtStart(instr->left()); | 878 LOperand* left = UseRegisterAtStart(instr->left()); |
| 859 LOperand* right = UseRegisterAtStart(instr->right()); | 879 LOperand* right = UseRegisterAtStart(instr->right()); |
| 860 LArithmeticD* result = new LArithmeticD(op, left, right); | 880 LArithmeticD* result = new LArithmeticD(op, left, right); |
| 861 return DefineSameAsFirst(result); | 881 return DefineSameAsFirst(result); |
| 862 } | 882 } |
| 863 | 883 |
| 864 | 884 |
| 865 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 885 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
| 866 HArithmeticBinaryOperation* instr) { | 886 HArithmeticBinaryOperation* instr) { |
| 867 ASSERT(op == Token::ADD || | 887 ASSERT(op == Token::ADD || |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1129 new LInstanceOf(UseFixed(instr->left(), r0), | 1149 new LInstanceOf(UseFixed(instr->left(), r0), |
| 1130 UseFixed(instr->right(), r1)); | 1150 UseFixed(instr->right(), r1)); |
| 1131 return MarkAsCall(DefineFixed(result, r0), instr); | 1151 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1132 } | 1152 } |
| 1133 | 1153 |
| 1134 | 1154 |
| 1135 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( | 1155 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( |
| 1136 HInstanceOfKnownGlobal* instr) { | 1156 HInstanceOfKnownGlobal* instr) { |
| 1137 LInstanceOfKnownGlobal* result = | 1157 LInstanceOfKnownGlobal* result = |
| 1138 new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0), FixedTemp(r4)); | 1158 new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0), FixedTemp(r4)); |
| 1139 MarkAsSaveDoubles(result); | 1159 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1140 return AssignEnvironment(AssignPointerMap(DefineFixed(result, r0))); | |
| 1141 } | 1160 } |
| 1142 | 1161 |
| 1143 | 1162 |
| 1144 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { | 1163 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { |
| 1145 LOperand* function = UseFixed(instr->function(), r1); | 1164 LOperand* function = UseFixed(instr->function(), r1); |
| 1146 LOperand* receiver = UseFixed(instr->receiver(), r0); | 1165 LOperand* receiver = UseFixed(instr->receiver(), r0); |
| 1147 LOperand* length = UseFixed(instr->length(), r2); | 1166 LOperand* length = UseFixed(instr->length(), r2); |
| 1148 LOperand* elements = UseFixed(instr->elements(), r3); | 1167 LOperand* elements = UseFixed(instr->elements(), r3); |
| 1149 LApplyArguments* result = new LApplyArguments(function, | 1168 LApplyArguments* result = new LApplyArguments(function, |
| 1150 receiver, | 1169 receiver, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1186 | 1205 |
| 1187 LInstruction* LChunkBuilder::DoCallConstantFunction( | 1206 LInstruction* LChunkBuilder::DoCallConstantFunction( |
| 1188 HCallConstantFunction* instr) { | 1207 HCallConstantFunction* instr) { |
| 1189 argument_count_ -= instr->argument_count(); | 1208 argument_count_ -= instr->argument_count(); |
| 1190 return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr); | 1209 return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr); |
| 1191 } | 1210 } |
| 1192 | 1211 |
| 1193 | 1212 |
| 1194 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { | 1213 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { |
| 1195 BuiltinFunctionId op = instr->op(); | 1214 BuiltinFunctionId op = instr->op(); |
| 1196 LOperand* input = UseRegisterAtStart(instr->value()); | 1215 if (op == kMathLog || op == kMathSin || op == kMathCos) { |
| 1197 LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL; | 1216 LOperand* input = UseFixedDouble(instr->value(), d2); |
| 1198 LUnaryMathOperation* result = new LUnaryMathOperation(input, temp); | 1217 LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL); |
| 1199 switch (op) { | 1218 return MarkAsCall(DefineFixedDouble(result, d2), instr); |
| 1200 case kMathAbs: | 1219 } else { |
| 1201 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 1220 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1202 case kMathFloor: | 1221 LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL; |
| 1203 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1222 LUnaryMathOperation* result = new LUnaryMathOperation(input, temp); |
| 1204 case kMathSqrt: | 1223 switch (op) { |
| 1205 return DefineSameAsFirst(result); | 1224 case kMathAbs: |
| 1206 case kMathRound: | 1225 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| 1207 Abort("MathRound LUnaryMathOperation not implemented"); | 1226 case kMathFloor: |
| 1208 return NULL; | 1227 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
| 1209 case kMathPowHalf: | 1228 case kMathSqrt: |
| 1210 Abort("MathPowHalf LUnaryMathOperation not implemented"); | 1229 return DefineSameAsFirst(result); |
| 1211 return NULL; | 1230 case kMathRound: |
| 1212 case kMathLog: | 1231 return AssignEnvironment(DefineAsRegister(result)); |
| 1213 Abort("MathLog LUnaryMathOperation not implemented"); | 1232 case kMathPowHalf: |
| 1214 return NULL; | 1233 return DefineSameAsFirst(result); |
| 1215 case kMathCos: | 1234 default: |
| 1216 Abort("MathCos LUnaryMathOperation not implemented"); | 1235 UNREACHABLE(); |
| 1217 return NULL; | 1236 return NULL; |
| 1218 case kMathSin: | 1237 } |
| 1219 Abort("MathSin LUnaryMathOperation not implemented"); | |
| 1220 return NULL; | |
| 1221 default: | |
| 1222 UNREACHABLE(); | |
| 1223 return NULL; | |
| 1224 } | 1238 } |
| 1225 } | 1239 } |
| 1226 | 1240 |
| 1227 | 1241 |
| 1228 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { | 1242 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { |
| 1229 ASSERT(instr->key()->representation().IsTagged()); | 1243 ASSERT(instr->key()->representation().IsTagged()); |
| 1230 argument_count_ -= instr->argument_count(); | 1244 argument_count_ -= instr->argument_count(); |
| 1231 LOperand* key = UseFixed(instr->key(), r2); | 1245 LOperand* key = UseFixed(instr->key(), r2); |
| 1232 return MarkAsCall(DefineFixed(new LCallKeyed(key), r0), instr); | 1246 return MarkAsCall(DefineFixed(new LCallKeyed(key), r0), instr); |
| 1233 } | 1247 } |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1329 | 1343 |
| 1330 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1344 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1331 if (instr->representation().IsInteger32()) { | 1345 if (instr->representation().IsInteger32()) { |
| 1332 // TODO(1042) The fixed register allocation | 1346 // TODO(1042) The fixed register allocation |
| 1333 // is needed because we call GenericBinaryOpStub from | 1347 // is needed because we call GenericBinaryOpStub from |
| 1334 // the generated code, which requires registers r0 | 1348 // the generated code, which requires registers r0 |
| 1335 // and r1 to be used. We should remove that | 1349 // and r1 to be used. We should remove that |
| 1336 // when we provide a native implementation. | 1350 // when we provide a native implementation. |
| 1337 ASSERT(instr->left()->representation().IsInteger32()); | 1351 ASSERT(instr->left()->representation().IsInteger32()); |
| 1338 ASSERT(instr->right()->representation().IsInteger32()); | 1352 ASSERT(instr->right()->representation().IsInteger32()); |
| 1339 LOperand* value = UseFixed(instr->left(), r0); | 1353 |
| 1340 LOperand* divisor = UseFixed(instr->right(), r1); | 1354 LInstruction* result; |
| 1341 LInstruction* result = DefineFixed(new LModI(value, divisor), r0); | 1355 if (instr->HasPowerOf2Divisor()) { |
| 1342 result = AssignEnvironment(AssignPointerMap(result)); | 1356 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); |
| 1357 LOperand* value = UseRegisterAtStart(instr->left()); |
| 1358 LModI* mod = new LModI(value, UseOrConstant(instr->right())); |
| 1359 result = DefineSameAsFirst(mod); |
| 1360 result = AssignEnvironment(result); |
| 1361 } else { |
| 1362 LOperand* value = UseFixed(instr->left(), r0); |
| 1363 LOperand* divisor = UseFixed(instr->right(), r1); |
| 1364 result = DefineFixed(new LModI(value, divisor), r0); |
| 1365 result = AssignEnvironment(AssignPointerMap(result)); |
| 1366 } |
| 1367 |
| 1343 return result; | 1368 return result; |
| 1344 } else if (instr->representation().IsTagged()) { | 1369 } else if (instr->representation().IsTagged()) { |
| 1345 return DoArithmeticT(Token::MOD, instr); | 1370 return DoArithmeticT(Token::MOD, instr); |
| 1346 } else { | 1371 } else { |
| 1347 ASSERT(instr->representation().IsDouble()); | 1372 ASSERT(instr->representation().IsDouble()); |
| 1348 // We call a C function for double modulo. It can't trigger a GC. | 1373 // We call a C function for double modulo. It can't trigger a GC. |
| 1349 // We need to use fixed result register for the call. | 1374 // We need to use fixed result register for the call. |
| 1350 // TODO(fschneider): Allow any register as input registers. | 1375 // TODO(fschneider): Allow any register as input registers. |
| 1351 LOperand* left = UseFixedDouble(instr->left(), d1); | 1376 LOperand* left = UseFixedDouble(instr->left(), d1); |
| 1352 LOperand* right = UseFixedDouble(instr->right(), d2); | 1377 LOperand* right = UseFixedDouble(instr->right(), d2); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1411 } else if (instr->representation().IsDouble()) { | 1436 } else if (instr->representation().IsDouble()) { |
| 1412 return DoArithmeticD(Token::ADD, instr); | 1437 return DoArithmeticD(Token::ADD, instr); |
| 1413 } else { | 1438 } else { |
| 1414 ASSERT(instr->representation().IsTagged()); | 1439 ASSERT(instr->representation().IsTagged()); |
| 1415 return DoArithmeticT(Token::ADD, instr); | 1440 return DoArithmeticT(Token::ADD, instr); |
| 1416 } | 1441 } |
| 1417 } | 1442 } |
| 1418 | 1443 |
| 1419 | 1444 |
| 1420 LInstruction* LChunkBuilder::DoPower(HPower* instr) { | 1445 LInstruction* LChunkBuilder::DoPower(HPower* instr) { |
| 1421 Abort("LPower instruction not implemented on ARM"); | 1446 ASSERT(instr->representation().IsDouble()); |
| 1422 return NULL; | 1447 // We call a C function for double power. It can't trigger a GC. |
| 1448 // We need to use fixed result register for the call. |
| 1449 Representation exponent_type = instr->right()->representation(); |
| 1450 ASSERT(instr->left()->representation().IsDouble()); |
| 1451 LOperand* left = UseFixedDouble(instr->left(), d1); |
| 1452 LOperand* right = exponent_type.IsDouble() ? |
| 1453 UseFixedDouble(instr->right(), d2) : |
| 1454 UseFixed(instr->right(), r0); |
| 1455 LPower* result = new LPower(left, right); |
| 1456 return MarkAsCall(DefineFixedDouble(result, d3), |
| 1457 instr, |
| 1458 CAN_DEOPTIMIZE_EAGERLY); |
| 1423 } | 1459 } |
| 1424 | 1460 |
| 1425 | 1461 |
| 1426 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { | 1462 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { |
| 1427 Token::Value op = instr->token(); | 1463 Token::Value op = instr->token(); |
| 1428 Representation r = instr->GetInputRepresentation(); | 1464 Representation r = instr->GetInputRepresentation(); |
| 1429 if (r.IsInteger32()) { | 1465 if (r.IsInteger32()) { |
| 1430 ASSERT(instr->left()->representation().IsInteger32()); | 1466 ASSERT(instr->left()->representation().IsInteger32()); |
| 1431 ASSERT(instr->right()->representation().IsInteger32()); | 1467 ASSERT(instr->right()->representation().IsInteger32()); |
| 1432 LOperand* left = UseRegisterAtStart(instr->left()); | 1468 LOperand* left = UseRegisterAtStart(instr->left()); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1484 | 1520 |
| 1485 | 1521 |
| 1486 LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) { | 1522 LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) { |
| 1487 ASSERT(instr->value()->representation().IsTagged()); | 1523 ASSERT(instr->value()->representation().IsTagged()); |
| 1488 LOperand* value = UseRegisterAtStart(instr->value()); | 1524 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1489 | 1525 |
| 1490 return DefineAsRegister(new LHasInstanceType(value)); | 1526 return DefineAsRegister(new LHasInstanceType(value)); |
| 1491 } | 1527 } |
| 1492 | 1528 |
| 1493 | 1529 |
| 1530 LInstruction* LChunkBuilder::DoGetCachedArrayIndex( |
| 1531 HGetCachedArrayIndex* instr) { |
| 1532 ASSERT(instr->value()->representation().IsTagged()); |
| 1533 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1534 |
| 1535 return DefineAsRegister(new LGetCachedArrayIndex(value)); |
| 1536 } |
| 1537 |
| 1538 |
| 1494 LInstruction* LChunkBuilder::DoHasCachedArrayIndex( | 1539 LInstruction* LChunkBuilder::DoHasCachedArrayIndex( |
| 1495 HHasCachedArrayIndex* instr) { | 1540 HHasCachedArrayIndex* instr) { |
| 1496 ASSERT(instr->value()->representation().IsTagged()); | 1541 ASSERT(instr->value()->representation().IsTagged()); |
| 1497 LOperand* value = UseRegister(instr->value()); | 1542 LOperand* value = UseRegister(instr->value()); |
| 1498 | 1543 |
| 1499 return DefineAsRegister(new LHasCachedArrayIndex(value)); | 1544 return DefineAsRegister(new LHasCachedArrayIndex(value)); |
| 1500 } | 1545 } |
| 1501 | 1546 |
| 1502 | 1547 |
| 1503 LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) { | 1548 LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) { |
| 1504 ASSERT(instr->value()->representation().IsTagged()); | 1549 ASSERT(instr->value()->representation().IsTagged()); |
| 1505 LOperand* value = UseTempRegister(instr->value()); | 1550 LOperand* value = UseTempRegister(instr->value()); |
| 1506 return DefineSameAsFirst(new LClassOfTest(value)); | 1551 return DefineSameAsFirst(new LClassOfTest(value)); |
| 1507 } | 1552 } |
| 1508 | 1553 |
| 1509 | 1554 |
| 1510 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) { | 1555 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) { |
| 1511 LOperand* array = UseRegisterAtStart(instr->value()); | 1556 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1512 return DefineAsRegister(new LJSArrayLength(array)); | 1557 return DefineAsRegister(new LJSArrayLength(array)); |
| 1513 } | 1558 } |
| 1514 | 1559 |
| 1515 | 1560 |
| 1516 LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) { | 1561 LInstruction* LChunkBuilder::DoExternalArrayLength( |
| 1562 HExternalArrayLength* instr) { |
| 1517 LOperand* array = UseRegisterAtStart(instr->value()); | 1563 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1518 return DefineAsRegister(new LPixelArrayLength(array)); | 1564 return DefineAsRegister(new LExternalArrayLength(array)); |
| 1519 } | 1565 } |
| 1520 | 1566 |
| 1521 | 1567 |
| 1522 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) { | 1568 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) { |
| 1523 LOperand* array = UseRegisterAtStart(instr->value()); | 1569 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1524 return DefineAsRegister(new LFixedArrayLength(array)); | 1570 return DefineAsRegister(new LFixedArrayLength(array)); |
| 1525 } | 1571 } |
| 1526 | 1572 |
| 1527 | 1573 |
| 1528 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { | 1574 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1557 if (from.IsTagged()) { | 1603 if (from.IsTagged()) { |
| 1558 if (to.IsDouble()) { | 1604 if (to.IsDouble()) { |
| 1559 LOperand* value = UseRegister(instr->value()); | 1605 LOperand* value = UseRegister(instr->value()); |
| 1560 LNumberUntagD* res = new LNumberUntagD(value); | 1606 LNumberUntagD* res = new LNumberUntagD(value); |
| 1561 return AssignEnvironment(DefineAsRegister(res)); | 1607 return AssignEnvironment(DefineAsRegister(res)); |
| 1562 } else { | 1608 } else { |
| 1563 ASSERT(to.IsInteger32()); | 1609 ASSERT(to.IsInteger32()); |
| 1564 LOperand* value = UseRegister(instr->value()); | 1610 LOperand* value = UseRegister(instr->value()); |
| 1565 bool needs_check = !instr->value()->type().IsSmi(); | 1611 bool needs_check = !instr->value()->type().IsSmi(); |
| 1566 LInstruction* res = NULL; | 1612 LInstruction* res = NULL; |
| 1567 if (needs_check) { | 1613 if (!needs_check) { |
| 1568 res = DefineSameAsFirst(new LTaggedToI(value, FixedTemp(d1))); | 1614 res = DefineSameAsFirst(new LSmiUntag(value, needs_check)); |
| 1569 } else { | 1615 } else { |
| 1570 res = DefineSameAsFirst(new LSmiUntag(value, needs_check)); | 1616 LOperand* temp1 = TempRegister(); |
| 1571 } | 1617 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() |
| 1572 if (needs_check) { | 1618 : NULL; |
| 1619 LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d3) |
| 1620 : NULL; |
| 1621 res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3)); |
| 1573 res = AssignEnvironment(res); | 1622 res = AssignEnvironment(res); |
| 1574 } | 1623 } |
| 1575 return res; | 1624 return res; |
| 1576 } | 1625 } |
| 1577 } else if (from.IsDouble()) { | 1626 } else if (from.IsDouble()) { |
| 1578 if (to.IsTagged()) { | 1627 if (to.IsTagged()) { |
| 1579 LOperand* value = UseRegister(instr->value()); | 1628 LOperand* value = UseRegister(instr->value()); |
| 1580 LOperand* temp1 = TempRegister(); | 1629 LOperand* temp1 = TempRegister(); |
| 1581 LOperand* temp2 = TempRegister(); | 1630 LOperand* temp2 = TempRegister(); |
| 1582 | 1631 |
| 1583 // Make sure that the temp and result_temp registers are | 1632 // Make sure that the temp and result_temp registers are |
| 1584 // different. | 1633 // different. |
| 1585 LUnallocated* result_temp = TempRegister(); | 1634 LUnallocated* result_temp = TempRegister(); |
| 1586 LNumberTagD* result = new LNumberTagD(value, temp1, temp2); | 1635 LNumberTagD* result = new LNumberTagD(value, temp1, temp2); |
| 1587 Define(result, result_temp); | 1636 Define(result, result_temp); |
| 1588 return AssignPointerMap(result); | 1637 return AssignPointerMap(result); |
| 1589 } else { | 1638 } else { |
| 1590 ASSERT(to.IsInteger32()); | 1639 ASSERT(to.IsInteger32()); |
| 1591 LOperand* value = UseRegister(instr->value()); | 1640 LOperand* value = UseRegister(instr->value()); |
| 1592 LDoubleToI* res = new LDoubleToI(value, TempRegister()); | 1641 LDoubleToI* res = |
| 1642 new LDoubleToI(value, |
| 1643 TempRegister(), |
| 1644 instr->CanTruncateToInt32() ? TempRegister() : NULL); |
| 1593 return AssignEnvironment(DefineAsRegister(res)); | 1645 return AssignEnvironment(DefineAsRegister(res)); |
| 1594 } | 1646 } |
| 1595 } else if (from.IsInteger32()) { | 1647 } else if (from.IsInteger32()) { |
| 1596 if (to.IsTagged()) { | 1648 if (to.IsTagged()) { |
| 1597 HValue* val = instr->value(); | 1649 HValue* val = instr->value(); |
| 1598 LOperand* value = UseRegister(val); | 1650 LOperand* value = UseRegister(val); |
| 1599 if (val->HasRange() && val->range()->IsInSmiRange()) { | 1651 if (val->HasRange() && val->range()->IsInSmiRange()) { |
| 1600 return DefineSameAsFirst(new LSmiTag(value)); | 1652 return DefineSameAsFirst(new LSmiTag(value)); |
| 1601 } else { | 1653 } else { |
| 1602 LNumberTagI* result = new LNumberTagI(value); | 1654 LNumberTagI* result = new LNumberTagI(value); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1693 } | 1745 } |
| 1694 | 1746 |
| 1695 | 1747 |
| 1696 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { | 1748 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { |
| 1697 LOperand* context = UseRegisterAtStart(instr->value()); | 1749 LOperand* context = UseRegisterAtStart(instr->value()); |
| 1698 return DefineAsRegister(new LLoadContextSlot(context)); | 1750 return DefineAsRegister(new LLoadContextSlot(context)); |
| 1699 } | 1751 } |
| 1700 | 1752 |
| 1701 | 1753 |
| 1702 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { | 1754 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { |
| 1703 LOperand* context = UseTempRegister(instr->context()); | 1755 LOperand* context; |
| 1704 LOperand* value; | 1756 LOperand* value; |
| 1705 if (instr->NeedsWriteBarrier()) { | 1757 if (instr->NeedsWriteBarrier()) { |
| 1758 context = UseTempRegister(instr->context()); |
| 1706 value = UseTempRegister(instr->value()); | 1759 value = UseTempRegister(instr->value()); |
| 1707 } else { | 1760 } else { |
| 1761 context = UseRegister(instr->context()); |
| 1708 value = UseRegister(instr->value()); | 1762 value = UseRegister(instr->value()); |
| 1709 } | 1763 } |
| 1710 return new LStoreContextSlot(context, value); | 1764 return new LStoreContextSlot(context, value); |
| 1711 } | 1765 } |
| 1712 | 1766 |
| 1713 | 1767 |
| 1714 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { | 1768 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { |
| 1715 return DefineAsRegister( | 1769 return DefineAsRegister( |
| 1716 new LLoadNamedField(UseRegisterAtStart(instr->object()))); | 1770 new LLoadNamedField(UseRegisterAtStart(instr->object()))); |
| 1717 } | 1771 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1730 new LLoadFunctionPrototype(UseRegister(instr->function())))); | 1784 new LLoadFunctionPrototype(UseRegister(instr->function())))); |
| 1731 } | 1785 } |
| 1732 | 1786 |
| 1733 | 1787 |
| 1734 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) { | 1788 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) { |
| 1735 LOperand* input = UseRegisterAtStart(instr->value()); | 1789 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1736 return DefineAsRegister(new LLoadElements(input)); | 1790 return DefineAsRegister(new LLoadElements(input)); |
| 1737 } | 1791 } |
| 1738 | 1792 |
| 1739 | 1793 |
| 1740 LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer( | 1794 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( |
| 1741 HLoadPixelArrayExternalPointer* instr) { | 1795 HLoadExternalArrayPointer* instr) { |
| 1742 LOperand* input = UseRegisterAtStart(instr->value()); | 1796 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1743 return DefineAsRegister(new LLoadPixelArrayExternalPointer(input)); | 1797 return DefineAsRegister(new LLoadExternalArrayPointer(input)); |
| 1744 } | 1798 } |
| 1745 | 1799 |
| 1746 | 1800 |
| 1747 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( | 1801 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( |
| 1748 HLoadKeyedFastElement* instr) { | 1802 HLoadKeyedFastElement* instr) { |
| 1749 ASSERT(instr->representation().IsTagged()); | 1803 ASSERT(instr->representation().IsTagged()); |
| 1750 ASSERT(instr->key()->representation().IsInteger32()); | 1804 ASSERT(instr->key()->representation().IsInteger32()); |
| 1751 LOperand* obj = UseRegisterAtStart(instr->object()); | 1805 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 1752 LOperand* key = UseRegisterAtStart(instr->key()); | 1806 LOperand* key = UseRegisterAtStart(instr->key()); |
| 1753 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); | 1807 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1790 ? UseTempRegister(instr->value()) | 1844 ? UseTempRegister(instr->value()) |
| 1791 : UseRegisterAtStart(instr->value()); | 1845 : UseRegisterAtStart(instr->value()); |
| 1792 LOperand* key = needs_write_barrier | 1846 LOperand* key = needs_write_barrier |
| 1793 ? UseTempRegister(instr->key()) | 1847 ? UseTempRegister(instr->key()) |
| 1794 : UseRegisterOrConstantAtStart(instr->key()); | 1848 : UseRegisterOrConstantAtStart(instr->key()); |
| 1795 | 1849 |
| 1796 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); | 1850 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); |
| 1797 } | 1851 } |
| 1798 | 1852 |
| 1799 | 1853 |
| 1854 LInstruction* LChunkBuilder::DoStorePixelArrayElement( |
| 1855 HStorePixelArrayElement* instr) { |
| 1856 ASSERT(instr->value()->representation().IsInteger32()); |
| 1857 ASSERT(instr->external_pointer()->representation().IsExternal()); |
| 1858 ASSERT(instr->key()->representation().IsInteger32()); |
| 1859 |
| 1860 LOperand* external_pointer = UseRegister(instr->external_pointer()); |
| 1861 LOperand* value = UseTempRegister(instr->value()); // changed by clamp. |
| 1862 LOperand* key = UseRegister(instr->key()); |
| 1863 |
| 1864 return new LStorePixelArrayElement(external_pointer, key, value); |
| 1865 } |
| 1866 |
| 1867 |
| 1800 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { | 1868 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { |
| 1801 LOperand* obj = UseFixed(instr->object(), r2); | 1869 LOperand* obj = UseFixed(instr->object(), r2); |
| 1802 LOperand* key = UseFixed(instr->key(), r1); | 1870 LOperand* key = UseFixed(instr->key(), r1); |
| 1803 LOperand* val = UseFixed(instr->value(), r0); | 1871 LOperand* val = UseFixed(instr->value(), r0); |
| 1804 | 1872 |
| 1805 ASSERT(instr->object()->representation().IsTagged()); | 1873 ASSERT(instr->object()->representation().IsTagged()); |
| 1806 ASSERT(instr->key()->representation().IsTagged()); | 1874 ASSERT(instr->key()->representation().IsTagged()); |
| 1807 ASSERT(instr->value()->representation().IsTagged()); | 1875 ASSERT(instr->value()->representation().IsTagged()); |
| 1808 | 1876 |
| 1809 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr); | 1877 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1835 | 1903 |
| 1836 | 1904 |
| 1837 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { | 1905 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { |
| 1838 LOperand* string = UseRegister(instr->string()); | 1906 LOperand* string = UseRegister(instr->string()); |
| 1839 LOperand* index = UseRegisterOrConstant(instr->index()); | 1907 LOperand* index = UseRegisterOrConstant(instr->index()); |
| 1840 LStringCharCodeAt* result = new LStringCharCodeAt(string, index); | 1908 LStringCharCodeAt* result = new LStringCharCodeAt(string, index); |
| 1841 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1909 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
| 1842 } | 1910 } |
| 1843 | 1911 |
| 1844 | 1912 |
| 1913 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { |
| 1914 LOperand* char_code = UseRegister(instr->value()); |
| 1915 LStringCharFromCode* result = new LStringCharFromCode(char_code); |
| 1916 return AssignPointerMap(DefineAsRegister(result)); |
| 1917 } |
| 1918 |
| 1919 |
| 1845 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) { | 1920 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) { |
| 1846 LOperand* string = UseRegisterAtStart(instr->value()); | 1921 LOperand* string = UseRegisterAtStart(instr->value()); |
| 1847 return DefineAsRegister(new LStringLength(string)); | 1922 return DefineAsRegister(new LStringLength(string)); |
| 1848 } | 1923 } |
| 1849 | 1924 |
| 1850 | 1925 |
| 1851 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { | 1926 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { |
| 1852 return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr); | 1927 return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr); |
| 1853 } | 1928 } |
| 1854 | 1929 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1895 } | 1970 } |
| 1896 | 1971 |
| 1897 | 1972 |
| 1898 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { | 1973 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { |
| 1899 argument_count_ -= instr->argument_count(); | 1974 argument_count_ -= instr->argument_count(); |
| 1900 return MarkAsCall(DefineFixed(new LCallStub, r0), instr); | 1975 return MarkAsCall(DefineFixed(new LCallStub, r0), instr); |
| 1901 } | 1976 } |
| 1902 | 1977 |
| 1903 | 1978 |
| 1904 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { | 1979 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { |
| 1905 // There are no real uses of the arguments object (we bail out in all other | 1980 // There are no real uses of the arguments object. |
| 1906 // cases). | 1981 // arguments.length and element access are supported directly on |
| 1982 // stack arguments, and any real arguments object use causes a bailout. |
| 1983 // So this value is never used. |
| 1907 return NULL; | 1984 return NULL; |
| 1908 } | 1985 } |
| 1909 | 1986 |
| 1910 | 1987 |
| 1911 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { | 1988 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { |
| 1912 LOperand* arguments = UseRegister(instr->arguments()); | 1989 LOperand* arguments = UseRegister(instr->arguments()); |
| 1913 LOperand* length = UseTempRegister(instr->length()); | 1990 LOperand* length = UseTempRegister(instr->length()); |
| 1914 LOperand* index = UseRegister(instr->index()); | 1991 LOperand* index = UseRegister(instr->index()); |
| 1915 LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index); | 1992 LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index); |
| 1916 return AssignEnvironment(DefineAsRegister(result)); | 1993 return AssignEnvironment(DefineAsRegister(result)); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1985 | 2062 |
| 1986 | 2063 |
| 1987 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 2064 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 1988 HEnvironment* outer = current_block_->last_environment()->outer(); | 2065 HEnvironment* outer = current_block_->last_environment()->outer(); |
| 1989 current_block_->UpdateEnvironment(outer); | 2066 current_block_->UpdateEnvironment(outer); |
| 1990 return NULL; | 2067 return NULL; |
| 1991 } | 2068 } |
| 1992 | 2069 |
| 1993 | 2070 |
| 1994 } } // namespace v8::internal | 2071 } } // namespace v8::internal |
| OLD | NEW |