| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 namespace v8 { | 36 namespace v8 { |
| 37 namespace internal { | 37 namespace internal { |
| 38 | 38 |
| 39 #define DEFINE_COMPILE(type) \ | 39 #define DEFINE_COMPILE(type) \ |
| 40 void L##type::CompileToNative(LCodeGen* generator) { \ | 40 void L##type::CompileToNative(LCodeGen* generator) { \ |
| 41 generator->Do##type(this); \ | 41 generator->Do##type(this); \ |
| 42 } | 42 } |
| 43 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE) | 43 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE) |
| 44 #undef DEFINE_COMPILE | 44 #undef DEFINE_COMPILE |
| 45 | 45 |
| 46 LOsrEntry::LOsrEntry() { | |
| 47 for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) { | |
| 48 register_spills_[i] = NULL; | |
| 49 } | |
| 50 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) { | |
| 51 double_register_spills_[i] = NULL; | |
| 52 } | |
| 53 } | |
| 54 | |
| 55 | |
| 56 void LOsrEntry::MarkSpilledRegister(int allocation_index, | |
| 57 LOperand* spill_operand) { | |
| 58 ASSERT(spill_operand->IsStackSlot()); | |
| 59 ASSERT(register_spills_[allocation_index] == NULL); | |
| 60 register_spills_[allocation_index] = spill_operand; | |
| 61 } | |
| 62 | |
| 63 | |
| 64 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, | |
| 65 LOperand* spill_operand) { | |
| 66 ASSERT(spill_operand->IsDoubleStackSlot()); | |
| 67 ASSERT(double_register_spills_[allocation_index] == NULL); | |
| 68 double_register_spills_[allocation_index] = spill_operand; | |
| 69 } | |
| 70 | |
| 71 | 46 |
| 72 #ifdef DEBUG | 47 #ifdef DEBUG |
| 73 void LInstruction::VerifyCall() { | 48 void LInstruction::VerifyCall() { |
| 74 // Call instructions can use only fixed registers as temporaries and | 49 // Call instructions can use only fixed registers as temporaries and |
| 75 // outputs because all registers are blocked by the calling convention. | 50 // outputs because all registers are blocked by the calling convention. |
| 76 // Inputs operands must use a fixed register or use-at-start policy or | 51 // Inputs operands must use a fixed register or use-at-start policy or |
| 77 // a non-register policy. | 52 // a non-register policy. |
| 78 ASSERT(Output() == NULL || | 53 ASSERT(Output() == NULL || |
| 79 LUnallocated::cast(Output())->HasFixedPolicy() || | 54 LUnallocated::cast(Output())->HasFixedPolicy() || |
| 80 !LUnallocated::cast(Output())->HasRegisterPolicy()); | 55 !LUnallocated::cast(Output())->HasRegisterPolicy()); |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 | 449 |
| 475 void LTransitionElementsKind::PrintDataTo(StringStream* stream) { | 450 void LTransitionElementsKind::PrintDataTo(StringStream* stream) { |
| 476 object()->PrintTo(stream); | 451 object()->PrintTo(stream); |
| 477 stream->Add(" %p -> %p", *original_map(), *transitioned_map()); | 452 stream->Add(" %p -> %p", *original_map(), *transitioned_map()); |
| 478 } | 453 } |
| 479 | 454 |
| 480 | 455 |
| 481 LPlatformChunk* LChunkBuilder::Build() { | 456 LPlatformChunk* LChunkBuilder::Build() { |
| 482 ASSERT(is_unused()); | 457 ASSERT(is_unused()); |
| 483 chunk_ = new(zone()) LPlatformChunk(info(), graph()); | 458 chunk_ = new(zone()) LPlatformChunk(info(), graph()); |
| 484 HPhase phase("L_Building chunk", chunk_); | 459 LPhase phase("L_Building chunk", chunk_); |
| 485 status_ = BUILDING; | 460 status_ = BUILDING; |
| 486 | 461 |
| 487 // Reserve the first spill slot for the state of dynamic alignment. | 462 // Reserve the first spill slot for the state of dynamic alignment. |
| 488 if (info()->IsOptimizing()) { | 463 if (info()->IsOptimizing()) { |
| 489 int alignment_state_index = chunk_->GetNextSpillIndex(false); | 464 int alignment_state_index = chunk_->GetNextSpillIndex(false); |
| 490 ASSERT_EQ(alignment_state_index, 0); | 465 ASSERT_EQ(alignment_state_index, 0); |
| 491 USE(alignment_state_index); | 466 USE(alignment_state_index); |
| 492 } | 467 } |
| 493 | 468 |
| 494 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 469 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); |
| (...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1053 HValue* value = instr->value(); | 1028 HValue* value = instr->value(); |
| 1054 if (value->EmitAtUses()) { | 1029 if (value->EmitAtUses()) { |
| 1055 ASSERT(value->IsConstant()); | 1030 ASSERT(value->IsConstant()); |
| 1056 ASSERT(!value->representation().IsDouble()); | 1031 ASSERT(!value->representation().IsDouble()); |
| 1057 HBasicBlock* successor = HConstant::cast(value)->BooleanValue() | 1032 HBasicBlock* successor = HConstant::cast(value)->BooleanValue() |
| 1058 ? instr->FirstSuccessor() | 1033 ? instr->FirstSuccessor() |
| 1059 : instr->SecondSuccessor(); | 1034 : instr->SecondSuccessor(); |
| 1060 return new(zone()) LGoto(successor->block_id()); | 1035 return new(zone()) LGoto(successor->block_id()); |
| 1061 } | 1036 } |
| 1062 | 1037 |
| 1063 // Untagged integers or doubles, smis and booleans don't require a | 1038 ToBooleanStub::Types expected = instr->expected_input_types(); |
| 1064 // deoptimization environment nor a temp register. | 1039 |
| 1040 // Tagged values that are not known smis or booleans require a |
| 1041 // deoptimization environment. If the instruction is generic no |
| 1042 // environment is needed since all cases are handled. |
| 1065 Representation rep = value->representation(); | 1043 Representation rep = value->representation(); |
| 1066 HType type = value->type(); | 1044 HType type = value->type(); |
| 1067 if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) { | 1045 if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) { |
| 1068 return new(zone()) LBranch(UseRegister(value), NULL); | 1046 return new(zone()) LBranch(UseRegister(value), NULL); |
| 1069 } | 1047 } |
| 1070 | 1048 |
| 1071 ToBooleanStub::Types expected = instr->expected_input_types(); | 1049 bool needs_temp = expected.NeedsMap() || expected.IsEmpty(); |
| 1050 LOperand* temp = needs_temp ? TempRegister() : NULL; |
| 1051 |
| 1052 // The Generic stub does not have a deopt, so we need no environment. |
| 1053 if (expected.IsGeneric()) { |
| 1054 return new(zone()) LBranch(UseRegister(value), temp); |
| 1055 } |
| 1056 |
| 1072 // We need a temporary register when we have to access the map *or* we have | 1057 // We need a temporary register when we have to access the map *or* we have |
| 1073 // no type info yet, in which case we handle all cases (including the ones | 1058 // no type info yet, in which case we handle all cases (including the ones |
| 1074 // involving maps). | 1059 // involving maps). |
| 1075 bool needs_temp = expected.NeedsMap() || expected.IsEmpty(); | |
| 1076 LOperand* temp = needs_temp ? TempRegister() : NULL; | |
| 1077 return AssignEnvironment(new(zone()) LBranch(UseRegister(value), temp)); | 1060 return AssignEnvironment(new(zone()) LBranch(UseRegister(value), temp)); |
| 1078 } | 1061 } |
| 1079 | 1062 |
| 1080 | 1063 |
| 1081 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { | 1064 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { |
| 1082 return new(zone()) LDebugBreak(); | 1065 return new(zone()) LDebugBreak(); |
| 1083 } | 1066 } |
| 1084 | 1067 |
| 1085 | 1068 |
| 1086 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { | 1069 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1360 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { | 1343 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { |
| 1361 LOperand* context = UseFixed(instr->context(), esi); | 1344 LOperand* context = UseFixed(instr->context(), esi); |
| 1362 LOperand* constructor = UseFixed(instr->constructor(), edi); | 1345 LOperand* constructor = UseFixed(instr->constructor(), edi); |
| 1363 argument_count_ -= instr->argument_count(); | 1346 argument_count_ -= instr->argument_count(); |
| 1364 LCallNew* result = new(zone()) LCallNew(context, constructor); | 1347 LCallNew* result = new(zone()) LCallNew(context, constructor); |
| 1365 return MarkAsCall(DefineFixed(result, eax), instr); | 1348 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1366 } | 1349 } |
| 1367 | 1350 |
| 1368 | 1351 |
| 1369 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) { | 1352 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) { |
| 1370 ASSERT(FLAG_optimize_constructed_arrays); | |
| 1371 LOperand* context = UseFixed(instr->context(), esi); | 1353 LOperand* context = UseFixed(instr->context(), esi); |
| 1372 LOperand* constructor = UseFixed(instr->constructor(), edi); | 1354 LOperand* constructor = UseFixed(instr->constructor(), edi); |
| 1373 argument_count_ -= instr->argument_count(); | 1355 argument_count_ -= instr->argument_count(); |
| 1374 LCallNewArray* result = new(zone()) LCallNewArray(context, constructor); | 1356 LCallNewArray* result = new(zone()) LCallNewArray(context, constructor); |
| 1375 return MarkAsCall(DefineFixed(result, eax), instr); | 1357 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1376 } | 1358 } |
| 1377 | 1359 |
| 1378 | 1360 |
| 1379 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { | 1361 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { |
| 1380 LOperand* context = UseFixed(instr->context(), esi); | 1362 LOperand* context = UseFixed(instr->context(), esi); |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1536 if (instr->HasPowerOf2Divisor()) { | 1518 if (instr->HasPowerOf2Divisor()) { |
| 1537 ASSERT(!right->CanBeZero()); | 1519 ASSERT(!right->CanBeZero()); |
| 1538 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), | 1520 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), |
| 1539 UseOrConstant(right), | 1521 UseOrConstant(right), |
| 1540 NULL); | 1522 NULL); |
| 1541 LInstruction* result = DefineSameAsFirst(mod); | 1523 LInstruction* result = DefineSameAsFirst(mod); |
| 1542 return (left->CanBeNegative() && | 1524 return (left->CanBeNegative() && |
| 1543 instr->CheckFlag(HValue::kBailoutOnMinusZero)) | 1525 instr->CheckFlag(HValue::kBailoutOnMinusZero)) |
| 1544 ? AssignEnvironment(result) | 1526 ? AssignEnvironment(result) |
| 1545 : result; | 1527 : result; |
| 1546 } else if (instr->has_fixed_right_arg()) { | 1528 } else if (instr->fixed_right_arg().has_value) { |
| 1547 LModI* mod = new(zone()) LModI(UseRegister(left), | 1529 LModI* mod = new(zone()) LModI(UseRegister(left), |
| 1548 UseRegisterAtStart(right), | 1530 UseRegisterAtStart(right), |
| 1549 NULL); | 1531 NULL); |
| 1550 return AssignEnvironment(DefineSameAsFirst(mod)); | 1532 return AssignEnvironment(DefineSameAsFirst(mod)); |
| 1551 } else { | 1533 } else { |
| 1552 // The temporary operand is necessary to ensure that right is not | 1534 // The temporary operand is necessary to ensure that right is not |
| 1553 // allocated into edx. | 1535 // allocated into edx. |
| 1554 LModI* mod = new(zone()) LModI(UseFixed(left, eax), | 1536 LModI* mod = new(zone()) LModI(UseFixed(left, eax), |
| 1555 UseRegister(right), | 1537 UseRegister(right), |
| 1556 FixedTemp(edx)); | 1538 FixedTemp(edx)); |
| (...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2017 DefineAsRegister(new(zone()) LDoubleToI(value, temp))); | 1999 DefineAsRegister(new(zone()) LDoubleToI(value, temp))); |
| 2018 } | 2000 } |
| 2019 } else if (from.IsInteger32()) { | 2001 } else if (from.IsInteger32()) { |
| 2020 info()->MarkAsDeferredCalling(); | 2002 info()->MarkAsDeferredCalling(); |
| 2021 if (to.IsTagged()) { | 2003 if (to.IsTagged()) { |
| 2022 HValue* val = instr->value(); | 2004 HValue* val = instr->value(); |
| 2023 LOperand* value = UseRegister(val); | 2005 LOperand* value = UseRegister(val); |
| 2024 if (val->HasRange() && val->range()->IsInSmiRange()) { | 2006 if (val->HasRange() && val->range()->IsInSmiRange()) { |
| 2025 return DefineSameAsFirst(new(zone()) LSmiTag(value)); | 2007 return DefineSameAsFirst(new(zone()) LSmiTag(value)); |
| 2026 } else if (val->CheckFlag(HInstruction::kUint32)) { | 2008 } else if (val->CheckFlag(HInstruction::kUint32)) { |
| 2027 LNumberTagU* result = new(zone()) LNumberTagU(value); | 2009 LOperand* temp = CpuFeatures::IsSupported(SSE2) ? FixedTemp(xmm1) |
| 2010 : NULL; |
| 2011 LNumberTagU* result = new(zone()) LNumberTagU(value, temp); |
| 2028 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 2012 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| 2029 } else { | 2013 } else { |
| 2030 LNumberTagI* result = new(zone()) LNumberTagI(value); | 2014 LNumberTagI* result = new(zone()) LNumberTagI(value); |
| 2031 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 2015 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| 2032 } | 2016 } |
| 2033 } else if (to.IsSmi()) { | 2017 } else if (to.IsSmi()) { |
| 2034 HValue* val = instr->value(); | 2018 HValue* val = instr->value(); |
| 2035 LOperand* value = UseRegister(val); | 2019 LOperand* value = UseRegister(val); |
| 2036 LInstruction* result = | 2020 LInstruction* result = |
| 2037 DefineSameAsFirst(new(zone()) LInteger32ToSmi(value)); | 2021 DefineSameAsFirst(new(zone()) LInteger32ToSmi(value)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2049 return DefineAsRegister( | 2033 return DefineAsRegister( |
| 2050 new(zone()) LInteger32ToDouble(Use(instr->value()))); | 2034 new(zone()) LInteger32ToDouble(Use(instr->value()))); |
| 2051 } | 2035 } |
| 2052 } | 2036 } |
| 2053 } | 2037 } |
| 2054 UNREACHABLE(); | 2038 UNREACHABLE(); |
| 2055 return NULL; | 2039 return NULL; |
| 2056 } | 2040 } |
| 2057 | 2041 |
| 2058 | 2042 |
| 2059 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) { | 2043 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { |
| 2060 LOperand* value = UseAtStart(instr->value()); | 2044 LOperand* value = UseAtStart(instr->value()); |
| 2061 return AssignEnvironment(new(zone()) LCheckNonSmi(value)); | 2045 return AssignEnvironment(new(zone()) LCheckNonSmi(value)); |
| 2062 } | 2046 } |
| 2063 | 2047 |
| 2064 | 2048 |
| 2065 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { | 2049 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
| 2066 LOperand* value = UseRegisterAtStart(instr->value()); | 2050 LOperand* value = UseRegisterAtStart(instr->value()); |
| 2067 LOperand* temp = TempRegister(); | 2051 LOperand* temp = TempRegister(); |
| 2068 LCheckInstanceType* result = new(zone()) LCheckInstanceType(value, temp); | 2052 LCheckInstanceType* result = new(zone()) LCheckInstanceType(value, temp); |
| 2069 return AssignEnvironment(result); | 2053 return AssignEnvironment(result); |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2541 return AssignPointerMap(DefineAsRegister(result)); | 2525 return AssignPointerMap(DefineAsRegister(result)); |
| 2542 } | 2526 } |
| 2543 | 2527 |
| 2544 | 2528 |
| 2545 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) { | 2529 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) { |
| 2546 LOperand* string = UseRegisterAtStart(instr->value()); | 2530 LOperand* string = UseRegisterAtStart(instr->value()); |
| 2547 return DefineAsRegister(new(zone()) LStringLength(string)); | 2531 return DefineAsRegister(new(zone()) LStringLength(string)); |
| 2548 } | 2532 } |
| 2549 | 2533 |
| 2550 | 2534 |
| 2535 LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) { |
| 2536 info()->MarkAsDeferredCalling(); |
| 2537 LOperand* context = UseAny(instr->context()); |
| 2538 LOperand* temp = TempRegister(); |
| 2539 LAllocateObject* result = new(zone()) LAllocateObject(context, temp); |
| 2540 return AssignPointerMap(DefineAsRegister(result)); |
| 2541 } |
| 2542 |
| 2543 |
| 2551 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { | 2544 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { |
| 2552 info()->MarkAsDeferredCalling(); | 2545 info()->MarkAsDeferredCalling(); |
| 2553 LOperand* context = UseAny(instr->context()); | 2546 LOperand* context = UseAny(instr->context()); |
| 2554 LOperand* size = instr->size()->IsConstant() | 2547 LOperand* size = instr->size()->IsConstant() |
| 2555 ? UseConstant(instr->size()) | 2548 ? UseConstant(instr->size()) |
| 2556 : UseTempRegister(instr->size()); | 2549 : UseTempRegister(instr->size()); |
| 2557 LOperand* temp = TempRegister(); | 2550 LOperand* temp = TempRegister(); |
| 2558 LAllocate* result = new(zone()) LAllocate(context, size, temp); | 2551 LAllocate* result = new(zone()) LAllocate(context, size, temp); |
| 2559 return AssignPointerMap(DefineAsRegister(result)); | 2552 return AssignPointerMap(DefineAsRegister(result)); |
| 2560 } | 2553 } |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2797 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2790 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2798 LOperand* object = UseRegister(instr->object()); | 2791 LOperand* object = UseRegister(instr->object()); |
| 2799 LOperand* index = UseTempRegister(instr->index()); | 2792 LOperand* index = UseTempRegister(instr->index()); |
| 2800 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); | 2793 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); |
| 2801 } | 2794 } |
| 2802 | 2795 |
| 2803 | 2796 |
| 2804 } } // namespace v8::internal | 2797 } } // namespace v8::internal |
| 2805 | 2798 |
| 2806 #endif // V8_TARGET_ARCH_IA32 | 2799 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |