| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 code->instr()->Mnemonic()); | 794 code->instr()->Mnemonic()); |
| 795 | 795 |
| 796 __ Bind(code->entry()); | 796 __ Bind(code->entry()); |
| 797 | 797 |
| 798 if (NeedsDeferredFrame()) { | 798 if (NeedsDeferredFrame()) { |
| 799 Comment(";;; Build frame"); | 799 Comment(";;; Build frame"); |
| 800 ASSERT(!frame_is_built_); | 800 ASSERT(!frame_is_built_); |
| 801 ASSERT(info()->IsStub()); | 801 ASSERT(info()->IsStub()); |
| 802 frame_is_built_ = true; | 802 frame_is_built_ = true; |
| 803 __ Push(lr, fp, cp); | 803 __ Push(lr, fp, cp); |
| 804 __ Mov(fp, Operand(Smi::FromInt(StackFrame::STUB))); | 804 __ Mov(fp, Smi::FromInt(StackFrame::STUB)); |
| 805 __ Push(fp); | 805 __ Push(fp); |
| 806 __ Add(fp, __ StackPointer(), | 806 __ Add(fp, __ StackPointer(), |
| 807 StandardFrameConstants::kFixedFrameSizeFromFp); | 807 StandardFrameConstants::kFixedFrameSizeFromFp); |
| 808 Comment(";;; Deferred code"); | 808 Comment(";;; Deferred code"); |
| 809 } | 809 } |
| 810 | 810 |
| 811 code->Generate(); | 811 code->Generate(); |
| 812 | 812 |
| 813 if (NeedsDeferredFrame()) { | 813 if (NeedsDeferredFrame()) { |
| 814 Comment(";;; Destroy frame"); | 814 Comment(";;; Destroy frame"); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 } else { | 848 } else { |
| 849 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); | 849 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); |
| 850 } | 850 } |
| 851 if (deopt_jump_table_[i]->needs_frame) { | 851 if (deopt_jump_table_[i]->needs_frame) { |
| 852 ASSERT(!info()->saves_caller_doubles()); | 852 ASSERT(!info()->saves_caller_doubles()); |
| 853 | 853 |
| 854 UseScratchRegisterScope temps(masm()); | 854 UseScratchRegisterScope temps(masm()); |
| 855 Register stub_deopt_entry = temps.AcquireX(); | 855 Register stub_deopt_entry = temps.AcquireX(); |
| 856 Register stub_marker = temps.AcquireX(); | 856 Register stub_marker = temps.AcquireX(); |
| 857 | 857 |
| 858 __ Mov(stub_deopt_entry, | 858 __ Mov(stub_deopt_entry, ExternalReference::ForDeoptEntry(entry)); |
| 859 Operand(ExternalReference::ForDeoptEntry(entry))); | |
| 860 if (needs_frame.is_bound()) { | 859 if (needs_frame.is_bound()) { |
| 861 __ B(&needs_frame); | 860 __ B(&needs_frame); |
| 862 } else { | 861 } else { |
| 863 __ Bind(&needs_frame); | 862 __ Bind(&needs_frame); |
| 864 // This variant of deopt can only be used with stubs. Since we don't | 863 // This variant of deopt can only be used with stubs. Since we don't |
| 865 // have a function pointer to install in the stack frame that we're | 864 // have a function pointer to install in the stack frame that we're |
| 866 // building, install a special marker there instead. | 865 // building, install a special marker there instead. |
| 867 ASSERT(info()->IsStub()); | 866 ASSERT(info()->IsStub()); |
| 868 __ Mov(stub_marker, Operand(Smi::FromInt(StackFrame::STUB))); | 867 __ Mov(stub_marker, Smi::FromInt(StackFrame::STUB)); |
| 869 __ Push(lr, fp, cp, stub_marker); | 868 __ Push(lr, fp, cp, stub_marker); |
| 870 __ Add(fp, __ StackPointer(), 2 * kPointerSize); | 869 __ Add(fp, __ StackPointer(), 2 * kPointerSize); |
| 871 __ Call(stub_deopt_entry); | 870 __ Call(stub_deopt_entry); |
| 872 } | 871 } |
| 873 } else { | 872 } else { |
| 874 if (info()->saves_caller_doubles()) { | 873 if (info()->saves_caller_doubles()) { |
| 875 ASSERT(info()->IsStub()); | 874 ASSERT(info()->IsStub()); |
| 876 RestoreCallerDoubles(); | 875 RestoreCallerDoubles(); |
| 877 } | 876 } |
| 878 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 877 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 998 if (entry == NULL) { | 997 if (entry == NULL) { |
| 999 Abort(kBailoutWasNotPrepared); | 998 Abort(kBailoutWasNotPrepared); |
| 1000 } | 999 } |
| 1001 | 1000 |
| 1002 if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) { | 1001 if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) { |
| 1003 Label not_zero; | 1002 Label not_zero; |
| 1004 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); | 1003 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); |
| 1005 | 1004 |
| 1006 __ Push(x0, x1, x2); | 1005 __ Push(x0, x1, x2); |
| 1007 __ Mrs(x2, NZCV); | 1006 __ Mrs(x2, NZCV); |
| 1008 __ Mov(x0, Operand(count)); | 1007 __ Mov(x0, count); |
| 1009 __ Ldr(w1, MemOperand(x0)); | 1008 __ Ldr(w1, MemOperand(x0)); |
| 1010 __ Subs(x1, x1, 1); | 1009 __ Subs(x1, x1, 1); |
| 1011 __ B(gt, ¬_zero); | 1010 __ B(gt, ¬_zero); |
| 1012 __ Mov(w1, FLAG_deopt_every_n_times); | 1011 __ Mov(w1, FLAG_deopt_every_n_times); |
| 1013 __ Str(w1, MemOperand(x0)); | 1012 __ Str(w1, MemOperand(x0)); |
| 1014 __ Pop(x2, x1, x0); | 1013 __ Pop(x2, x1, x0); |
| 1015 ASSERT(frame_is_built_); | 1014 ASSERT(frame_is_built_); |
| 1016 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 1015 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| 1017 __ Unreachable(); | 1016 __ Unreachable(); |
| 1018 | 1017 |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1545 } else { | 1544 } else { |
| 1546 ASSERT(instr->temp3() == NULL); | 1545 ASSERT(instr->temp3() == NULL); |
| 1547 } | 1546 } |
| 1548 } | 1547 } |
| 1549 | 1548 |
| 1550 | 1549 |
| 1551 void LCodeGen::DoDeferredAllocate(LAllocate* instr) { | 1550 void LCodeGen::DoDeferredAllocate(LAllocate* instr) { |
| 1552 // TODO(3095996): Get rid of this. For now, we need to make the | 1551 // TODO(3095996): Get rid of this. For now, we need to make the |
| 1553 // result register contain a valid pointer because it is already | 1552 // result register contain a valid pointer because it is already |
| 1554 // contained in the register pointer map. | 1553 // contained in the register pointer map. |
| 1555 __ Mov(ToRegister(instr->result()), Operand(Smi::FromInt(0))); | 1554 __ Mov(ToRegister(instr->result()), Smi::FromInt(0)); |
| 1556 | 1555 |
| 1557 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 1556 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 1558 // We're in a SafepointRegistersScope so we can use any scratch registers. | 1557 // We're in a SafepointRegistersScope so we can use any scratch registers. |
| 1559 Register size = x0; | 1558 Register size = x0; |
| 1560 if (instr->size()->IsConstantOperand()) { | 1559 if (instr->size()->IsConstantOperand()) { |
| 1561 __ Mov(size, Operand(ToSmi(LConstantOperand::cast(instr->size())))); | 1560 __ Mov(size, ToSmi(LConstantOperand::cast(instr->size()))); |
| 1562 } else { | 1561 } else { |
| 1563 __ SmiTag(size, ToRegister32(instr->size()).X()); | 1562 __ SmiTag(size, ToRegister32(instr->size()).X()); |
| 1564 } | 1563 } |
| 1565 int flags = AllocateDoubleAlignFlag::encode( | 1564 int flags = AllocateDoubleAlignFlag::encode( |
| 1566 instr->hydrogen()->MustAllocateDoubleAligned()); | 1565 instr->hydrogen()->MustAllocateDoubleAligned()); |
| 1567 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 1566 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
| 1568 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 1567 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
| 1569 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 1568 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 1570 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); | 1569 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); |
| 1571 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 1570 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
| 1572 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 1571 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 1573 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); | 1572 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); |
| 1574 } else { | 1573 } else { |
| 1575 flags = AllocateTargetSpace::update(flags, NEW_SPACE); | 1574 flags = AllocateTargetSpace::update(flags, NEW_SPACE); |
| 1576 } | 1575 } |
| 1577 __ Mov(x10, Operand(Smi::FromInt(flags))); | 1576 __ Mov(x10, Smi::FromInt(flags)); |
| 1578 __ Push(size, x10); | 1577 __ Push(size, x10); |
| 1579 | 1578 |
| 1580 CallRuntimeFromDeferred( | 1579 CallRuntimeFromDeferred( |
| 1581 Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); | 1580 Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); |
| 1582 __ StoreToSafepointRegisterSlot(x0, ToRegister(instr->result())); | 1581 __ StoreToSafepointRegisterSlot(x0, ToRegister(instr->result())); |
| 1583 } | 1582 } |
| 1584 | 1583 |
| 1585 | 1584 |
| 1586 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 1585 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
| 1587 Register receiver = ToRegister(instr->receiver()); | 1586 Register receiver = ToRegister(instr->receiver()); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1647 ASSERT(masm()->StackPointer().Is(jssp)); | 1646 ASSERT(masm()->StackPointer().Is(jssp)); |
| 1648 __ Sub(result, jssp, 2 * kPointerSize); | 1647 __ Sub(result, jssp, 2 * kPointerSize); |
| 1649 } else { | 1648 } else { |
| 1650 ASSERT(instr->temp() != NULL); | 1649 ASSERT(instr->temp() != NULL); |
| 1651 Register previous_fp = ToRegister(instr->temp()); | 1650 Register previous_fp = ToRegister(instr->temp()); |
| 1652 | 1651 |
| 1653 __ Ldr(previous_fp, | 1652 __ Ldr(previous_fp, |
| 1654 MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 1653 MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 1655 __ Ldr(result, | 1654 __ Ldr(result, |
| 1656 MemOperand(previous_fp, StandardFrameConstants::kContextOffset)); | 1655 MemOperand(previous_fp, StandardFrameConstants::kContextOffset)); |
| 1657 __ Cmp(result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1656 __ Cmp(result, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 1658 __ Csel(result, fp, previous_fp, ne); | 1657 __ Csel(result, fp, previous_fp, ne); |
| 1659 } | 1658 } |
| 1660 } | 1659 } |
| 1661 | 1660 |
| 1662 | 1661 |
| 1663 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 1662 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
| 1664 Register elements = ToRegister(instr->elements()); | 1663 Register elements = ToRegister(instr->elements()); |
| 1665 Register result = ToRegister32(instr->result()); | 1664 Register result = ToRegister32(instr->result()); |
| 1666 Label done; | 1665 Label done; |
| 1667 | 1666 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1772 if (instr->hydrogen()->skip_check()) return; | 1771 if (instr->hydrogen()->skip_check()) return; |
| 1773 | 1772 |
| 1774 ASSERT(instr->hydrogen()->length()->representation().IsInteger32()); | 1773 ASSERT(instr->hydrogen()->length()->representation().IsInteger32()); |
| 1775 Register length = ToRegister32(instr->length()); | 1774 Register length = ToRegister32(instr->length()); |
| 1776 | 1775 |
| 1777 if (instr->index()->IsConstantOperand()) { | 1776 if (instr->index()->IsConstantOperand()) { |
| 1778 int constant_index = | 1777 int constant_index = |
| 1779 ToInteger32(LConstantOperand::cast(instr->index())); | 1778 ToInteger32(LConstantOperand::cast(instr->index())); |
| 1780 | 1779 |
| 1781 if (instr->hydrogen()->length()->representation().IsSmi()) { | 1780 if (instr->hydrogen()->length()->representation().IsSmi()) { |
| 1782 __ Cmp(length, Operand(Smi::FromInt(constant_index))); | 1781 __ Cmp(length, Smi::FromInt(constant_index)); |
| 1783 } else { | 1782 } else { |
| 1784 __ Cmp(length, Operand(constant_index)); | 1783 __ Cmp(length, constant_index); |
| 1785 } | 1784 } |
| 1786 } else { | 1785 } else { |
| 1787 ASSERT(instr->hydrogen()->index()->representation().IsInteger32()); | 1786 ASSERT(instr->hydrogen()->index()->representation().IsInteger32()); |
| 1788 __ Cmp(length, ToRegister32(instr->index())); | 1787 __ Cmp(length, ToRegister32(instr->index())); |
| 1789 } | 1788 } |
| 1790 Condition condition = instr->hydrogen()->allow_equality() ? lo : ls; | 1789 Condition condition = instr->hydrogen()->allow_equality() ? lo : ls; |
| 1791 ApplyCheckIf(condition, instr); | 1790 ApplyCheckIf(condition, instr); |
| 1792 } | 1791 } |
| 1793 | 1792 |
| 1794 | 1793 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1812 ASSERT(r.IsTagged()); | 1811 ASSERT(r.IsTagged()); |
| 1813 Register value = ToRegister(instr->value()); | 1812 Register value = ToRegister(instr->value()); |
| 1814 HType type = instr->hydrogen()->value()->type(); | 1813 HType type = instr->hydrogen()->value()->type(); |
| 1815 | 1814 |
| 1816 if (type.IsBoolean()) { | 1815 if (type.IsBoolean()) { |
| 1817 ASSERT(!info()->IsStub()); | 1816 ASSERT(!info()->IsStub()); |
| 1818 __ CompareRoot(value, Heap::kTrueValueRootIndex); | 1817 __ CompareRoot(value, Heap::kTrueValueRootIndex); |
| 1819 EmitBranch(instr, eq); | 1818 EmitBranch(instr, eq); |
| 1820 } else if (type.IsSmi()) { | 1819 } else if (type.IsSmi()) { |
| 1821 ASSERT(!info()->IsStub()); | 1820 ASSERT(!info()->IsStub()); |
| 1822 EmitCompareAndBranch(instr, ne, value, Operand(Smi::FromInt(0))); | 1821 EmitCompareAndBranch(instr, ne, value, Smi::FromInt(0)); |
| 1823 } else if (type.IsJSArray()) { | 1822 } else if (type.IsJSArray()) { |
| 1824 ASSERT(!info()->IsStub()); | 1823 ASSERT(!info()->IsStub()); |
| 1825 EmitGoto(instr->TrueDestination(chunk())); | 1824 EmitGoto(instr->TrueDestination(chunk())); |
| 1826 } else if (type.IsHeapNumber()) { | 1825 } else if (type.IsHeapNumber()) { |
| 1827 ASSERT(!info()->IsStub()); | 1826 ASSERT(!info()->IsStub()); |
| 1828 __ Ldr(double_scratch(), FieldMemOperand(value, | 1827 __ Ldr(double_scratch(), FieldMemOperand(value, |
| 1829 HeapNumber::kValueOffset)); | 1828 HeapNumber::kValueOffset)); |
| 1830 // Test the double value. Zero and NaN are false. | 1829 // Test the double value. Zero and NaN are false. |
| 1831 EmitBranchIfNonZeroNumber(instr, double_scratch(), double_scratch()); | 1830 EmitBranchIfNonZeroNumber(instr, double_scratch(), double_scratch()); |
| 1832 } else if (type.IsString()) { | 1831 } else if (type.IsString()) { |
| (...skipping 1189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3022 { | 3021 { |
| 3023 // Below we use Factory::the_hole_value() on purpose instead of loading from | 3022 // Below we use Factory::the_hole_value() on purpose instead of loading from |
| 3024 // the root array to force relocation and later be able to patch with a | 3023 // the root array to force relocation and later be able to patch with a |
| 3025 // custom value. | 3024 // custom value. |
| 3026 InstructionAccurateScope scope(masm(), 5); | 3025 InstructionAccurateScope scope(masm(), 5); |
| 3027 __ bind(&map_check); | 3026 __ bind(&map_check); |
| 3028 // Will be patched with the cached map. | 3027 // Will be patched with the cached map. |
| 3029 Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value()); | 3028 Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value()); |
| 3030 __ LoadRelocated(scratch, Operand(Handle<Object>(cell))); | 3029 __ LoadRelocated(scratch, Operand(Handle<Object>(cell))); |
| 3031 __ ldr(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset)); | 3030 __ ldr(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset)); |
| 3032 __ cmp(map, Operand(scratch)); | 3031 __ cmp(map, scratch); |
| 3033 __ b(&cache_miss, ne); | 3032 __ b(&cache_miss, ne); |
| 3034 // The address of this instruction is computed relative to the map check | 3033 // The address of this instruction is computed relative to the map check |
| 3035 // above, so check the size of the code generated. | 3034 // above, so check the size of the code generated. |
| 3036 ASSERT(masm()->InstructionsGeneratedSince(&map_check) == 4); | 3035 ASSERT(masm()->InstructionsGeneratedSince(&map_check) == 4); |
| 3037 // Will be patched with the cached result. | 3036 // Will be patched with the cached result. |
| 3038 __ LoadRelocated(result, Operand(factory()->the_hole_value())); | 3037 __ LoadRelocated(result, Operand(factory()->the_hole_value())); |
| 3039 } | 3038 } |
| 3040 __ B(&done); | 3039 __ B(&done); |
| 3041 | 3040 |
| 3042 // The inlined call site cache did not match. | 3041 // The inlined call site cache did not match. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3134 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 3133 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
| 3135 Register temp1 = ToRegister(instr->temp1()); | 3134 Register temp1 = ToRegister(instr->temp1()); |
| 3136 Register temp2 = ToRegister(instr->temp2()); | 3135 Register temp2 = ToRegister(instr->temp2()); |
| 3137 | 3136 |
| 3138 // Get the frame pointer for the calling frame. | 3137 // Get the frame pointer for the calling frame. |
| 3139 __ Ldr(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 3138 __ Ldr(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 3140 | 3139 |
| 3141 // Skip the arguments adaptor frame if it exists. | 3140 // Skip the arguments adaptor frame if it exists. |
| 3142 Label check_frame_marker; | 3141 Label check_frame_marker; |
| 3143 __ Ldr(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset)); | 3142 __ Ldr(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset)); |
| 3144 __ Cmp(temp2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 3143 __ Cmp(temp2, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 3145 __ B(ne, &check_frame_marker); | 3144 __ B(ne, &check_frame_marker); |
| 3146 __ Ldr(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset)); | 3145 __ Ldr(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset)); |
| 3147 | 3146 |
| 3148 // Check the marker in the calling frame. | 3147 // Check the marker in the calling frame. |
| 3149 __ Bind(&check_frame_marker); | 3148 __ Bind(&check_frame_marker); |
| 3150 __ Ldr(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); | 3149 __ Ldr(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); |
| 3151 | 3150 |
| 3152 EmitCompareAndBranch( | 3151 EmitCompareAndBranch( |
| 3153 instr, eq, temp1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); | 3152 instr, eq, temp1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); |
| 3154 } | 3153 } |
| (...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4128 // indicate that positive dividends are heavily favored, so the branching | 4127 // indicate that positive dividends are heavily favored, so the branching |
| 4129 // version performs better. | 4128 // version performs better. |
| 4130 HMod* hmod = instr->hydrogen(); | 4129 HMod* hmod = instr->hydrogen(); |
| 4131 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 4130 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
| 4132 Label dividend_is_not_negative, done; | 4131 Label dividend_is_not_negative, done; |
| 4133 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { | 4132 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { |
| 4134 __ Cmp(dividend, 0); | 4133 __ Cmp(dividend, 0); |
| 4135 __ B(pl, ÷nd_is_not_negative); | 4134 __ B(pl, ÷nd_is_not_negative); |
| 4136 // Note that this is correct even for kMinInt operands. | 4135 // Note that this is correct even for kMinInt operands. |
| 4137 __ Neg(dividend, dividend); | 4136 __ Neg(dividend, dividend); |
| 4138 __ And(dividend, dividend, Operand(mask)); | 4137 __ And(dividend, dividend, mask); |
| 4139 __ Negs(dividend, dividend); | 4138 __ Negs(dividend, dividend); |
| 4140 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4139 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 4141 DeoptimizeIf(eq, instr->environment()); | 4140 DeoptimizeIf(eq, instr->environment()); |
| 4142 } | 4141 } |
| 4143 __ B(&done); | 4142 __ B(&done); |
| 4144 } | 4143 } |
| 4145 | 4144 |
| 4146 __ bind(÷nd_is_not_negative); | 4145 __ bind(÷nd_is_not_negative); |
| 4147 __ And(dividend, dividend, Operand(mask)); | 4146 __ And(dividend, dividend, mask); |
| 4148 __ bind(&done); | 4147 __ bind(&done); |
| 4149 } | 4148 } |
| 4150 | 4149 |
| 4151 | 4150 |
| 4152 void LCodeGen::DoModByConstI(LModByConstI* instr) { | 4151 void LCodeGen::DoModByConstI(LModByConstI* instr) { |
| 4153 Register dividend = ToRegister32(instr->dividend()); | 4152 Register dividend = ToRegister32(instr->dividend()); |
| 4154 int32_t divisor = instr->divisor(); | 4153 int32_t divisor = instr->divisor(); |
| 4155 Register result = ToRegister32(instr->result()); | 4154 Register result = ToRegister32(instr->result()); |
| 4156 Register temp = ToRegister32(instr->temp()); | 4155 Register temp = ToRegister32(instr->temp()); |
| 4157 ASSERT(!AreAliased(dividend, result, temp)); | 4156 ASSERT(!AreAliased(dividend, result, temp)); |
| (...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4867 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 4866 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
| 4868 ASSERT(ToRegister(instr->context()).is(cp)); | 4867 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4869 Register scratch1 = x5; | 4868 Register scratch1 = x5; |
| 4870 Register scratch2 = x6; | 4869 Register scratch2 = x6; |
| 4871 ASSERT(instr->IsMarkedAsCall()); | 4870 ASSERT(instr->IsMarkedAsCall()); |
| 4872 | 4871 |
| 4873 ASM_UNIMPLEMENTED_BREAK("DoDeclareGlobals"); | 4872 ASM_UNIMPLEMENTED_BREAK("DoDeclareGlobals"); |
| 4874 // TODO(all): if Mov could handle object in new space then it could be used | 4873 // TODO(all): if Mov could handle object in new space then it could be used |
| 4875 // here. | 4874 // here. |
| 4876 __ LoadHeapObject(scratch1, instr->hydrogen()->pairs()); | 4875 __ LoadHeapObject(scratch1, instr->hydrogen()->pairs()); |
| 4877 __ Mov(scratch2, Operand(Smi::FromInt(instr->hydrogen()->flags()))); | 4876 __ Mov(scratch2, Smi::FromInt(instr->hydrogen()->flags())); |
| 4878 __ Push(cp, scratch1, scratch2); // The context is the first argument. | 4877 __ Push(cp, scratch1, scratch2); // The context is the first argument. |
| 4879 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 4878 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
| 4880 } | 4879 } |
| 4881 | 4880 |
| 4882 | 4881 |
| 4883 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 4882 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
| 4884 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4883 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 4885 LoadContextFromDeferred(instr->context()); | 4884 LoadContextFromDeferred(instr->context()); |
| 4886 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 4885 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); |
| 4887 RecordSafepointWithLazyDeopt( | 4886 RecordSafepointWithLazyDeopt( |
| (...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5580 __ Mov(x1, x0); | 5579 __ Mov(x1, x0); |
| 5581 | 5580 |
| 5582 __ Bind(&materialized); | 5581 __ Bind(&materialized); |
| 5583 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 5582 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
| 5584 Label allocated, runtime_allocate; | 5583 Label allocated, runtime_allocate; |
| 5585 | 5584 |
| 5586 __ Allocate(size, x0, x10, x11, &runtime_allocate, TAG_OBJECT); | 5585 __ Allocate(size, x0, x10, x11, &runtime_allocate, TAG_OBJECT); |
| 5587 __ B(&allocated); | 5586 __ B(&allocated); |
| 5588 | 5587 |
| 5589 __ Bind(&runtime_allocate); | 5588 __ Bind(&runtime_allocate); |
| 5590 __ Mov(x0, Operand(Smi::FromInt(size))); | 5589 __ Mov(x0, Smi::FromInt(size)); |
| 5591 __ Push(x1, x0); | 5590 __ Push(x1, x0); |
| 5592 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); | 5591 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); |
| 5593 __ Pop(x1); | 5592 __ Pop(x1); |
| 5594 | 5593 |
| 5595 __ Bind(&allocated); | 5594 __ Bind(&allocated); |
| 5596 // Copy the content into the newly allocated memory. | 5595 // Copy the content into the newly allocated memory. |
| 5597 __ CopyFields(x0, x1, CPURegList(x10, x11, x12), size / kPointerSize); | 5596 __ CopyFields(x0, x1, CPURegList(x10, x11, x12), size / kPointerSize); |
| 5598 } | 5597 } |
| 5599 | 5598 |
| 5600 | 5599 |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5814 | 5813 |
| 5815 | 5814 |
| 5816 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { | 5815 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { |
| 5817 Register object = ToRegister(instr->object()); | 5816 Register object = ToRegister(instr->object()); |
| 5818 Register index = ToRegister(instr->index()); | 5817 Register index = ToRegister(instr->index()); |
| 5819 Register result = ToRegister(instr->result()); | 5818 Register result = ToRegister(instr->result()); |
| 5820 | 5819 |
| 5821 __ AssertSmi(index); | 5820 __ AssertSmi(index); |
| 5822 | 5821 |
| 5823 Label out_of_object, done; | 5822 Label out_of_object, done; |
| 5824 __ Cmp(index, Operand(Smi::FromInt(0))); | 5823 __ Cmp(index, Smi::FromInt(0)); |
| 5825 __ B(lt, &out_of_object); | 5824 __ B(lt, &out_of_object); |
| 5826 | 5825 |
| 5827 STATIC_ASSERT(kPointerSizeLog2 > kSmiTagSize); | 5826 STATIC_ASSERT(kPointerSizeLog2 > kSmiTagSize); |
| 5828 __ Add(result, object, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 5827 __ Add(result, object, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
| 5829 __ Ldr(result, FieldMemOperand(result, JSObject::kHeaderSize)); | 5828 __ Ldr(result, FieldMemOperand(result, JSObject::kHeaderSize)); |
| 5830 | 5829 |
| 5831 __ B(&done); | 5830 __ B(&done); |
| 5832 | 5831 |
| 5833 __ Bind(&out_of_object); | 5832 __ Bind(&out_of_object); |
| 5834 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 5833 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 5835 // Index is equal to negated out of object property index plus 1. | 5834 // Index is equal to negated out of object property index plus 1. |
| 5836 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 5835 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
| 5837 __ Ldr(result, FieldMemOperand(result, | 5836 __ Ldr(result, FieldMemOperand(result, |
| 5838 FixedArray::kHeaderSize - kPointerSize)); | 5837 FixedArray::kHeaderSize - kPointerSize)); |
| 5839 __ Bind(&done); | 5838 __ Bind(&done); |
| 5840 } | 5839 } |
| 5841 | 5840 |
| 5842 } } // namespace v8::internal | 5841 } } // namespace v8::internal |
| OLD | NEW |