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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
181 | 181 |
182 // Deferred code is the last part of the instruction sequence. Mark | 182 // Deferred code is the last part of the instruction sequence. Mark |
183 // the generated code as done unless we bailed out. | 183 // the generated code as done unless we bailed out. |
184 if (!is_aborted()) status_ = DONE; | 184 if (!is_aborted()) status_ = DONE; |
185 return !is_aborted(); | 185 return !is_aborted(); |
186 } | 186 } |
187 | 187 |
188 | 188 |
189 bool LCodeGen::GenerateSafepointTable() { | 189 bool LCodeGen::GenerateSafepointTable() { |
190 ASSERT(is_done()); | 190 ASSERT(is_done()); |
191 // Ensure that patching a deoptimization point won't overwrite the table. | 191 // Ensure that there is space at the end of the code to write a number |
192 for (int i = 0; i < Assembler::kCallInstructionLength; i++) { | 192 // of jump instructions, as well as to afford writing a call near the end |
193 masm()->int3(); | 193 // of the code. |
194 // The jumps are used when there isn't room in the code stream to write | |
195 // a long call instruction. Instead it writes a shorter call to a nearby | |
196 // jump instruction. | |
fschneider
2011/02/02 12:54:16
The comment should say that this is used for lazy
Lasse Reichstein
2011/02/03 14:14:12
done.
| |
197 int short_deopts = safepoints_.CountShortDeoptimizationIntervals( | |
198 static_cast<unsigned>(MacroAssembler::kJumpInstructionLength)); | |
199 int byte_count = MacroAssembler::kCallInstructionLength + | |
200 (short_deopts) * MacroAssembler::kJumpInstructionLength; | |
201 while (byte_count > 0) { | |
202 __ int3(); | |
203 byte_count--; | |
194 } | 204 } |
195 safepoints_.Emit(masm(), StackSlotCount()); | 205 safepoints_.Emit(masm(), StackSlotCount()); |
196 return !is_aborted(); | 206 return !is_aborted(); |
197 } | 207 } |
198 | 208 |
199 | 209 |
200 Register LCodeGen::ToRegister(int index) const { | 210 Register LCodeGen::ToRegister(int index) const { |
201 return Register::FromAllocationIndex(index); | 211 return Register::FromAllocationIndex(index); |
202 } | 212 } |
203 | 213 |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
498 inlined_function_count_ = deoptimization_literals_.length(); | 508 inlined_function_count_ = deoptimization_literals_.length(); |
499 } | 509 } |
500 | 510 |
501 | 511 |
502 void LCodeGen::RecordSafepoint( | 512 void LCodeGen::RecordSafepoint( |
503 LPointerMap* pointers, | 513 LPointerMap* pointers, |
504 Safepoint::Kind kind, | 514 Safepoint::Kind kind, |
505 int arguments, | 515 int arguments, |
506 int deoptimization_index) { | 516 int deoptimization_index) { |
507 const ZoneList<LOperand*>* operands = pointers->operands(); | 517 const ZoneList<LOperand*>* operands = pointers->operands(); |
518 | |
508 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), | 519 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), |
509 kind, arguments, deoptimization_index); | 520 kind, arguments, deoptimization_index); |
510 for (int i = 0; i < operands->length(); i++) { | 521 for (int i = 0; i < operands->length(); i++) { |
511 LOperand* pointer = operands->at(i); | 522 LOperand* pointer = operands->at(i); |
512 if (pointer->IsStackSlot()) { | 523 if (pointer->IsStackSlot()) { |
513 safepoint.DefinePointerSlot(pointer->index()); | 524 safepoint.DefinePointerSlot(pointer->index()); |
514 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 525 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
515 safepoint.DefinePointerRegister(ToRegister(pointer)); | 526 safepoint.DefinePointerRegister(ToRegister(pointer)); |
516 } | 527 } |
517 } | 528 } |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
662 } | 673 } |
663 | 674 |
664 | 675 |
665 void LCodeGen::DoConstantT(LConstantT* instr) { | 676 void LCodeGen::DoConstantT(LConstantT* instr) { |
666 ASSERT(instr->result()->IsRegister()); | 677 ASSERT(instr->result()->IsRegister()); |
667 __ Move(ToRegister(instr->result()), instr->value()); | 678 __ Move(ToRegister(instr->result()), instr->value()); |
668 } | 679 } |
669 | 680 |
670 | 681 |
671 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 682 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
672 Abort("Unimplemented: %s", "DoJSArrayLength"); | 683 Register result = ToRegister(instr->result()); |
684 Register array = ToRegister(instr->InputAt(0)); | |
685 __ movq(result, FieldOperand(array, JSArray::kLengthOffset)); | |
673 } | 686 } |
674 | 687 |
675 | 688 |
676 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { | 689 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { |
677 Abort("Unimplemented: %s", "DoFixedArrayLength"); | 690 Abort("Unimplemented: %s", "DoFixedArrayLength"); |
678 } | 691 } |
679 | 692 |
680 | 693 |
681 void LCodeGen::DoValueOf(LValueOf* instr) { | 694 void LCodeGen::DoValueOf(LValueOf* instr) { |
682 Abort("Unimplemented: %s", "DoValueOf"); | 695 Abort("Unimplemented: %s", "DoValueOf"); |
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1388 __ push(rax); | 1401 __ push(rax); |
1389 __ CallRuntime(Runtime::kTraceExit, 1); | 1402 __ CallRuntime(Runtime::kTraceExit, 1); |
1390 } | 1403 } |
1391 __ movq(rsp, rbp); | 1404 __ movq(rsp, rbp); |
1392 __ pop(rbp); | 1405 __ pop(rbp); |
1393 __ ret((ParameterCount() + 1) * kPointerSize); | 1406 __ ret((ParameterCount() + 1) * kPointerSize); |
1394 } | 1407 } |
1395 | 1408 |
1396 | 1409 |
1397 void LCodeGen::DoLoadGlobal(LLoadGlobal* instr) { | 1410 void LCodeGen::DoLoadGlobal(LLoadGlobal* instr) { |
1398 Register result = ToRegister(instr->result()); | 1411 Abort("Unimplemented: %s", "DoLoadGlobal"); |
1399 if (result.is(rax)) { | |
1400 __ load_rax(instr->hydrogen()->cell().location(), | |
1401 RelocInfo::GLOBAL_PROPERTY_CELL); | |
1402 } else { | |
1403 __ movq(result, instr->hydrogen()->cell(), RelocInfo::GLOBAL_PROPERTY_CELL); | |
1404 __ movq(result, Operand(result, 0)); | |
1405 } | |
1406 if (instr->hydrogen()->check_hole_value()) { | |
1407 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | |
1408 DeoptimizeIf(equal, instr->environment()); | |
1409 } | |
1410 } | 1412 } |
1411 | 1413 |
1412 | 1414 |
1413 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { | 1415 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { |
1414 Register value = ToRegister(instr->InputAt(0)); | 1416 Abort("Unimplemented: %s", "DoStoreGlobal"); |
1415 if (value.is(rax)) { | |
1416 __ store_rax(instr->hydrogen()->cell().location(), | |
1417 RelocInfo::GLOBAL_PROPERTY_CELL); | |
1418 } else { | |
1419 __ movq(kScratchRegister, | |
1420 Handle<Object>::cast(instr->hydrogen()->cell()), | |
1421 RelocInfo::GLOBAL_PROPERTY_CELL); | |
1422 __ movq(Operand(kScratchRegister, 0), value); | |
1423 } | |
1424 } | 1417 } |
1425 | 1418 |
1426 | 1419 |
1427 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 1420 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
1428 Abort("Unimplemented: %s", "DoLoadContextSlot"); | 1421 Abort("Unimplemented: %s", "DoLoadContextSlot"); |
1429 } | 1422 } |
1430 | 1423 |
1431 | 1424 |
1432 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 1425 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
1433 Register object = ToRegister(instr->InputAt(0)); | 1426 Register object = ToRegister(instr->InputAt(0)); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1519 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | 1512 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { |
1520 Register result = ToRegister(instr->result()); | 1513 Register result = ToRegister(instr->result()); |
1521 __ movq(result, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 1514 __ movq(result, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
1522 __ movq(result, FieldOperand(result, GlobalObject::kGlobalReceiverOffset)); | 1515 __ movq(result, FieldOperand(result, GlobalObject::kGlobalReceiverOffset)); |
1523 } | 1516 } |
1524 | 1517 |
1525 | 1518 |
1526 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 1519 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
1527 int arity, | 1520 int arity, |
1528 LInstruction* instr) { | 1521 LInstruction* instr) { |
1529 Abort("Unimplemented: %s", "CallKnownFunction"); | 1522 // Change context if needed. |
1523 bool change_context = | |
1524 (graph()->info()->closure()->context() != function->context()) || | |
1525 scope()->contains_with() || | |
1526 (scope()->num_heap_slots() > 0); | |
1527 if (change_context) { | |
1528 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | |
1529 } | |
1530 | |
1531 // Set rax to arguments count if adaption is not needed. Assumes that rax | |
1532 // is available to write to at this point. | |
1533 if (!function->NeedsArgumentsAdaption()) { | |
1534 __ Set(rax, arity); | |
1535 } | |
1536 | |
1537 LPointerMap* pointers = instr->pointer_map(); | |
1538 RecordPosition(pointers->position()); | |
1539 | |
1540 // Invoke function. | |
1541 if (*function == *graph()->info()->closure()) { | |
1542 __ CallSelf(); | |
1543 } else { | |
1544 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | |
1545 } | |
1546 | |
1547 // Setup deoptimization. | |
1548 RegisterLazyDeoptimization(instr); | |
1549 | |
1550 // Restore context. | |
1551 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
1530 } | 1552 } |
1531 | 1553 |
1532 | 1554 |
1533 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 1555 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
1534 Abort("Unimplemented: %s", "DoCallConstantFunction"); | 1556 Abort("Unimplemented: %s", "DoCallConstantFunction"); |
1535 } | 1557 } |
1536 | 1558 |
1537 | 1559 |
1538 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 1560 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
1539 Abort("Unimplemented: %s", "DoDeferredMathAbsTaggedHeapNumber"); | 1561 Abort("Unimplemented: %s", "DoDeferredMathAbsTaggedHeapNumber"); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1604 Abort("Unimplemented: %s", "DoCallFunction"); | 1626 Abort("Unimplemented: %s", "DoCallFunction"); |
1605 } | 1627 } |
1606 | 1628 |
1607 | 1629 |
1608 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 1630 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
1609 Abort("Unimplemented: %s", "DoCallGlobal"); | 1631 Abort("Unimplemented: %s", "DoCallGlobal"); |
1610 } | 1632 } |
1611 | 1633 |
1612 | 1634 |
1613 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 1635 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
1614 Abort("Unimplemented: %s", "DoCallKnownGlobal"); | 1636 ASSERT(ToRegister(instr->result()).is(rax)); |
1637 __ Move(rdi, instr->target()); | |
1638 CallKnownFunction(instr->target(), instr->arity(), instr); | |
1615 } | 1639 } |
1616 | 1640 |
1617 | 1641 |
1618 void LCodeGen::DoCallNew(LCallNew* instr) { | 1642 void LCodeGen::DoCallNew(LCallNew* instr) { |
1619 ASSERT(ToRegister(instr->InputAt(0)).is(rdi)); | 1643 ASSERT(ToRegister(instr->InputAt(0)).is(rdi)); |
1620 ASSERT(ToRegister(instr->result()).is(rax)); | 1644 ASSERT(ToRegister(instr->result()).is(rax)); |
1621 | 1645 |
1622 Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1646 Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall)); |
1623 __ Set(rax, instr->arity()); | 1647 __ Set(rax, instr->arity()); |
1624 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); | 1648 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1810 ASSERT(input->IsRegister()); | 1834 ASSERT(input->IsRegister()); |
1811 Condition cc = masm()->CheckSmi(ToRegister(input)); | 1835 Condition cc = masm()->CheckSmi(ToRegister(input)); |
1812 if (instr->condition() != equal) { | 1836 if (instr->condition() != equal) { |
1813 cc = NegateCondition(cc); | 1837 cc = NegateCondition(cc); |
1814 } | 1838 } |
1815 DeoptimizeIf(cc, instr->environment()); | 1839 DeoptimizeIf(cc, instr->environment()); |
1816 } | 1840 } |
1817 | 1841 |
1818 | 1842 |
1819 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 1843 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
1820 Abort("Unimplemented: %s", "DoCheckInstanceType"); | 1844 Register input = ToRegister(instr->InputAt(0)); |
1845 InstanceType first = instr->hydrogen()->first(); | |
1846 InstanceType last = instr->hydrogen()->last(); | |
1847 | |
1848 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); | |
1849 | |
1850 // If there is only one type in the interval check for equality. | |
1851 if (first == last) { | |
1852 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | |
1853 Immediate(static_cast<int8_t>(first))); | |
1854 DeoptimizeIf(not_equal, instr->environment()); | |
1855 } else if (first == FIRST_STRING_TYPE && last == LAST_STRING_TYPE) { | |
1856 // String has a dedicated bit in instance type. | |
1857 __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | |
1858 Immediate(kIsNotStringMask)); | |
1859 DeoptimizeIf(not_zero, instr->environment()); | |
1860 } else { | |
1861 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | |
1862 Immediate(static_cast<int8_t>(first))); | |
1863 DeoptimizeIf(below, instr->environment()); | |
1864 // Omit check for the last type. | |
1865 if (last != LAST_TYPE) { | |
1866 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | |
1867 Immediate(static_cast<int8_t>(last))); | |
1868 DeoptimizeIf(above, instr->environment()); | |
1869 } | |
1870 } | |
1821 } | 1871 } |
1822 | 1872 |
1823 | 1873 |
1824 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { | 1874 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { |
1825 ASSERT(instr->InputAt(0)->IsRegister()); | 1875 ASSERT(instr->InputAt(0)->IsRegister()); |
1826 Register reg = ToRegister(instr->InputAt(0)); | 1876 Register reg = ToRegister(instr->InputAt(0)); |
1827 __ Cmp(reg, instr->hydrogen()->target()); | 1877 __ Cmp(reg, instr->hydrogen()->target()); |
1828 DeoptimizeIf(not_equal, instr->environment()); | 1878 DeoptimizeIf(not_equal, instr->environment()); |
1829 } | 1879 } |
1830 | 1880 |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2012 | 2062 |
2013 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 2063 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
2014 Abort("Unimplemented: %s", "DoOsrEntry"); | 2064 Abort("Unimplemented: %s", "DoOsrEntry"); |
2015 } | 2065 } |
2016 | 2066 |
2017 #undef __ | 2067 #undef __ |
2018 | 2068 |
2019 } } // namespace v8::internal | 2069 } } // namespace v8::internal |
2020 | 2070 |
2021 #endif // V8_TARGET_ARCH_X64 | 2071 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |