| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/crankshaft/mips64/lithium-codegen-mips64.h" | 5 #include "src/crankshaft/mips64/lithium-codegen-mips64.h" |
| 6 | 6 |
| 7 #include "src/builtins/builtins-constructor.h" | 7 #include "src/builtins/builtins-constructor.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/crankshaft/hydrogen-osr.h" | 10 #include "src/crankshaft/hydrogen-osr.h" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 | 84 |
| 85 | 85 |
| 86 void LCodeGen::SaveCallerDoubles() { | 86 void LCodeGen::SaveCallerDoubles() { |
| 87 DCHECK(info()->saves_caller_doubles()); | 87 DCHECK(info()->saves_caller_doubles()); |
| 88 DCHECK(NeedsEagerFrame()); | 88 DCHECK(NeedsEagerFrame()); |
| 89 Comment(";;; Save clobbered callee double registers"); | 89 Comment(";;; Save clobbered callee double registers"); |
| 90 int count = 0; | 90 int count = 0; |
| 91 BitVector* doubles = chunk()->allocated_double_registers(); | 91 BitVector* doubles = chunk()->allocated_double_registers(); |
| 92 BitVector::Iterator save_iterator(doubles); | 92 BitVector::Iterator save_iterator(doubles); |
| 93 while (!save_iterator.Done()) { | 93 while (!save_iterator.Done()) { |
| 94 __ sdc1(DoubleRegister::from_code(save_iterator.Current()), | 94 __ Sdc1(DoubleRegister::from_code(save_iterator.Current()), |
| 95 MemOperand(sp, count * kDoubleSize)); | 95 MemOperand(sp, count * kDoubleSize)); |
| 96 save_iterator.Advance(); | 96 save_iterator.Advance(); |
| 97 count++; | 97 count++; |
| 98 } | 98 } |
| 99 } | 99 } |
| 100 | 100 |
| 101 | 101 |
| 102 void LCodeGen::RestoreCallerDoubles() { | 102 void LCodeGen::RestoreCallerDoubles() { |
| 103 DCHECK(info()->saves_caller_doubles()); | 103 DCHECK(info()->saves_caller_doubles()); |
| 104 DCHECK(NeedsEagerFrame()); | 104 DCHECK(NeedsEagerFrame()); |
| 105 Comment(";;; Restore clobbered callee double registers"); | 105 Comment(";;; Restore clobbered callee double registers"); |
| 106 BitVector* doubles = chunk()->allocated_double_registers(); | 106 BitVector* doubles = chunk()->allocated_double_registers(); |
| 107 BitVector::Iterator save_iterator(doubles); | 107 BitVector::Iterator save_iterator(doubles); |
| 108 int count = 0; | 108 int count = 0; |
| 109 while (!save_iterator.Done()) { | 109 while (!save_iterator.Done()) { |
| 110 __ ldc1(DoubleRegister::from_code(save_iterator.Current()), | 110 __ Ldc1(DoubleRegister::from_code(save_iterator.Current()), |
| 111 MemOperand(sp, count * kDoubleSize)); | 111 MemOperand(sp, count * kDoubleSize)); |
| 112 save_iterator.Advance(); | 112 save_iterator.Advance(); |
| 113 count++; | 113 count++; |
| 114 } | 114 } |
| 115 } | 115 } |
| 116 | 116 |
| 117 | 117 |
| 118 bool LCodeGen::GeneratePrologue() { | 118 bool LCodeGen::GeneratePrologue() { |
| 119 DCHECK(is_generating()); | 119 DCHECK(is_generating()); |
| 120 | 120 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 141 int slots = GetStackSlotCount(); | 141 int slots = GetStackSlotCount(); |
| 142 if (slots > 0) { | 142 if (slots > 0) { |
| 143 if (FLAG_debug_code) { | 143 if (FLAG_debug_code) { |
| 144 __ Dsubu(sp, sp, Operand(slots * kPointerSize)); | 144 __ Dsubu(sp, sp, Operand(slots * kPointerSize)); |
| 145 __ Push(a0, a1); | 145 __ Push(a0, a1); |
| 146 __ Daddu(a0, sp, Operand(slots * kPointerSize)); | 146 __ Daddu(a0, sp, Operand(slots * kPointerSize)); |
| 147 __ li(a1, Operand(kSlotsZapValue)); | 147 __ li(a1, Operand(kSlotsZapValue)); |
| 148 Label loop; | 148 Label loop; |
| 149 __ bind(&loop); | 149 __ bind(&loop); |
| 150 __ Dsubu(a0, a0, Operand(kPointerSize)); | 150 __ Dsubu(a0, a0, Operand(kPointerSize)); |
| 151 __ sd(a1, MemOperand(a0, 2 * kPointerSize)); | 151 __ Sd(a1, MemOperand(a0, 2 * kPointerSize)); |
| 152 __ Branch(&loop, ne, a0, Operand(sp)); | 152 __ Branch(&loop, ne, a0, Operand(sp)); |
| 153 __ Pop(a0, a1); | 153 __ Pop(a0, a1); |
| 154 } else { | 154 } else { |
| 155 __ Dsubu(sp, sp, Operand(slots * kPointerSize)); | 155 __ Dsubu(sp, sp, Operand(slots * kPointerSize)); |
| 156 } | 156 } |
| 157 } | 157 } |
| 158 | 158 |
| 159 if (info()->saves_caller_doubles()) { | 159 if (info()->saves_caller_doubles()) { |
| 160 SaveCallerDoubles(); | 160 SaveCallerDoubles(); |
| 161 } | 161 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 191 __ push(a1); | 191 __ push(a1); |
| 192 __ Push(Smi::FromInt(info()->scope()->scope_type())); | 192 __ Push(Smi::FromInt(info()->scope()->scope_type())); |
| 193 __ CallRuntime(Runtime::kNewFunctionContext); | 193 __ CallRuntime(Runtime::kNewFunctionContext); |
| 194 } | 194 } |
| 195 } | 195 } |
| 196 RecordSafepoint(deopt_mode); | 196 RecordSafepoint(deopt_mode); |
| 197 | 197 |
| 198 // Context is returned in both v0. It replaces the context passed to us. | 198 // Context is returned in both v0. It replaces the context passed to us. |
| 199 // It's saved in the stack and kept live in cp. | 199 // It's saved in the stack and kept live in cp. |
| 200 __ mov(cp, v0); | 200 __ mov(cp, v0); |
| 201 __ sd(v0, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 201 __ Sd(v0, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 202 // Copy any necessary parameters into the context. | 202 // Copy any necessary parameters into the context. |
| 203 int num_parameters = info()->scope()->num_parameters(); | 203 int num_parameters = info()->scope()->num_parameters(); |
| 204 int first_parameter = info()->scope()->has_this_declaration() ? -1 : 0; | 204 int first_parameter = info()->scope()->has_this_declaration() ? -1 : 0; |
| 205 for (int i = first_parameter; i < num_parameters; i++) { | 205 for (int i = first_parameter; i < num_parameters; i++) { |
| 206 Variable* var = (i == -1) ? info()->scope()->receiver() | 206 Variable* var = (i == -1) ? info()->scope()->receiver() |
| 207 : info()->scope()->parameter(i); | 207 : info()->scope()->parameter(i); |
| 208 if (var->IsContextSlot()) { | 208 if (var->IsContextSlot()) { |
| 209 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 209 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
| 210 (num_parameters - 1 - i) * kPointerSize; | 210 (num_parameters - 1 - i) * kPointerSize; |
| 211 // Load parameter from stack. | 211 // Load parameter from stack. |
| 212 __ ld(a0, MemOperand(fp, parameter_offset)); | 212 __ Ld(a0, MemOperand(fp, parameter_offset)); |
| 213 // Store it in the context. | 213 // Store it in the context. |
| 214 MemOperand target = ContextMemOperand(cp, var->index()); | 214 MemOperand target = ContextMemOperand(cp, var->index()); |
| 215 __ sd(a0, target); | 215 __ Sd(a0, target); |
| 216 // Update the write barrier. This clobbers a3 and a0. | 216 // Update the write barrier. This clobbers a3 and a0. |
| 217 if (need_write_barrier) { | 217 if (need_write_barrier) { |
| 218 __ RecordWriteContextSlot( | 218 __ RecordWriteContextSlot( |
| 219 cp, target.offset(), a0, a3, GetRAState(), kSaveFPRegs); | 219 cp, target.offset(), a0, a3, GetRAState(), kSaveFPRegs); |
| 220 } else if (FLAG_debug_code) { | 220 } else if (FLAG_debug_code) { |
| 221 Label done; | 221 Label done; |
| 222 __ JumpIfInNewSpace(cp, a0, &done); | 222 __ JumpIfInNewSpace(cp, a0, &done); |
| 223 __ Abort(kExpectedNewSpaceObject); | 223 __ Abort(kExpectedNewSpaceObject); |
| 224 __ bind(&done); | 224 __ bind(&done); |
| 225 } | 225 } |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 DCHECK(constant->HasSmiValue()); | 410 DCHECK(constant->HasSmiValue()); |
| 411 __ li(scratch, Operand(Smi::FromInt(constant->Integer32Value()))); | 411 __ li(scratch, Operand(Smi::FromInt(constant->Integer32Value()))); |
| 412 } else if (r.IsDouble()) { | 412 } else if (r.IsDouble()) { |
| 413 Abort(kEmitLoadRegisterUnsupportedDoubleImmediate); | 413 Abort(kEmitLoadRegisterUnsupportedDoubleImmediate); |
| 414 } else { | 414 } else { |
| 415 DCHECK(r.IsSmiOrTagged()); | 415 DCHECK(r.IsSmiOrTagged()); |
| 416 __ li(scratch, literal); | 416 __ li(scratch, literal); |
| 417 } | 417 } |
| 418 return scratch; | 418 return scratch; |
| 419 } else if (op->IsStackSlot()) { | 419 } else if (op->IsStackSlot()) { |
| 420 __ ld(scratch, ToMemOperand(op)); | 420 __ Ld(scratch, ToMemOperand(op)); |
| 421 return scratch; | 421 return scratch; |
| 422 } | 422 } |
| 423 UNREACHABLE(); | 423 UNREACHABLE(); |
| 424 return scratch; | 424 return scratch; |
| 425 } | 425 } |
| 426 | 426 |
| 427 | 427 |
| 428 DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const { | 428 DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const { |
| 429 DCHECK(op->IsDoubleRegister()); | 429 DCHECK(op->IsDoubleRegister()); |
| 430 return ToDoubleRegister(op->index()); | 430 return ToDoubleRegister(op->index()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 447 __ mtc1(at, flt_scratch); | 447 __ mtc1(at, flt_scratch); |
| 448 __ cvt_d_w(dbl_scratch, flt_scratch); | 448 __ cvt_d_w(dbl_scratch, flt_scratch); |
| 449 return dbl_scratch; | 449 return dbl_scratch; |
| 450 } else if (r.IsDouble()) { | 450 } else if (r.IsDouble()) { |
| 451 Abort(kUnsupportedDoubleImmediate); | 451 Abort(kUnsupportedDoubleImmediate); |
| 452 } else if (r.IsTagged()) { | 452 } else if (r.IsTagged()) { |
| 453 Abort(kUnsupportedTaggedImmediate); | 453 Abort(kUnsupportedTaggedImmediate); |
| 454 } | 454 } |
| 455 } else if (op->IsStackSlot()) { | 455 } else if (op->IsStackSlot()) { |
| 456 MemOperand mem_op = ToMemOperand(op); | 456 MemOperand mem_op = ToMemOperand(op); |
| 457 __ ldc1(dbl_scratch, mem_op); | 457 __ Ldc1(dbl_scratch, mem_op); |
| 458 return dbl_scratch; | 458 return dbl_scratch; |
| 459 } | 459 } |
| 460 UNREACHABLE(); | 460 UNREACHABLE(); |
| 461 return dbl_scratch; | 461 return dbl_scratch; |
| 462 } | 462 } |
| 463 | 463 |
| 464 | 464 |
| 465 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { | 465 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { |
| 466 HConstant* constant = chunk_->LookupConstant(op); | 466 HConstant* constant = chunk_->LookupConstant(op); |
| 467 DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); | 467 DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 690 __ CallRuntime(function, num_arguments, save_doubles); | 690 __ CallRuntime(function, num_arguments, save_doubles); |
| 691 | 691 |
| 692 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 692 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 693 } | 693 } |
| 694 | 694 |
| 695 | 695 |
| 696 void LCodeGen::LoadContextFromDeferred(LOperand* context) { | 696 void LCodeGen::LoadContextFromDeferred(LOperand* context) { |
| 697 if (context->IsRegister()) { | 697 if (context->IsRegister()) { |
| 698 __ Move(cp, ToRegister(context)); | 698 __ Move(cp, ToRegister(context)); |
| 699 } else if (context->IsStackSlot()) { | 699 } else if (context->IsStackSlot()) { |
| 700 __ ld(cp, ToMemOperand(context)); | 700 __ Ld(cp, ToMemOperand(context)); |
| 701 } else if (context->IsConstantOperand()) { | 701 } else if (context->IsConstantOperand()) { |
| 702 HConstant* constant = | 702 HConstant* constant = |
| 703 chunk_->LookupConstant(LConstantOperand::cast(context)); | 703 chunk_->LookupConstant(LConstantOperand::cast(context)); |
| 704 __ li(cp, Handle<Object>::cast(constant->handle(isolate()))); | 704 __ li(cp, Handle<Object>::cast(constant->handle(isolate()))); |
| 705 } else { | 705 } else { |
| 706 UNREACHABLE(); | 706 UNREACHABLE(); |
| 707 } | 707 } |
| 708 } | 708 } |
| 709 | 709 |
| 710 | 710 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 Abort(kBailoutWasNotPrepared); | 769 Abort(kBailoutWasNotPrepared); |
| 770 return; | 770 return; |
| 771 } | 771 } |
| 772 | 772 |
| 773 if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) { | 773 if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) { |
| 774 Register scratch = scratch0(); | 774 Register scratch = scratch0(); |
| 775 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); | 775 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); |
| 776 Label no_deopt; | 776 Label no_deopt; |
| 777 __ Push(a1, scratch); | 777 __ Push(a1, scratch); |
| 778 __ li(scratch, Operand(count)); | 778 __ li(scratch, Operand(count)); |
| 779 __ lw(a1, MemOperand(scratch)); | 779 __ Lw(a1, MemOperand(scratch)); |
| 780 __ Subu(a1, a1, Operand(1)); | 780 __ Subu(a1, a1, Operand(1)); |
| 781 __ Branch(&no_deopt, ne, a1, Operand(zero_reg)); | 781 __ Branch(&no_deopt, ne, a1, Operand(zero_reg)); |
| 782 __ li(a1, Operand(FLAG_deopt_every_n_times)); | 782 __ li(a1, Operand(FLAG_deopt_every_n_times)); |
| 783 __ sw(a1, MemOperand(scratch)); | 783 __ Sw(a1, MemOperand(scratch)); |
| 784 __ Pop(a1, scratch); | 784 __ Pop(a1, scratch); |
| 785 | 785 |
| 786 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 786 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| 787 __ bind(&no_deopt); | 787 __ bind(&no_deopt); |
| 788 __ sw(a1, MemOperand(scratch)); | 788 __ Sw(a1, MemOperand(scratch)); |
| 789 __ Pop(a1, scratch); | 789 __ Pop(a1, scratch); |
| 790 } | 790 } |
| 791 | 791 |
| 792 if (info()->ShouldTrapOnDeopt()) { | 792 if (info()->ShouldTrapOnDeopt()) { |
| 793 Label skip; | 793 Label skip; |
| 794 if (condition != al) { | 794 if (condition != al) { |
| 795 __ Branch(&skip, NegateCondition(condition), src1, src2); | 795 __ Branch(&skip, NegateCondition(condition), src1, src2); |
| 796 } | 796 } |
| 797 __ stop("trap_on_deopt"); | 797 __ stop("trap_on_deopt"); |
| 798 __ bind(&skip); | 798 __ bind(&skip); |
| (...skipping 959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1758 } | 1758 } |
| 1759 | 1759 |
| 1760 | 1760 |
| 1761 void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) { | 1761 void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) { |
| 1762 String::Encoding encoding = instr->hydrogen()->encoding(); | 1762 String::Encoding encoding = instr->hydrogen()->encoding(); |
| 1763 Register string = ToRegister(instr->string()); | 1763 Register string = ToRegister(instr->string()); |
| 1764 Register result = ToRegister(instr->result()); | 1764 Register result = ToRegister(instr->result()); |
| 1765 | 1765 |
| 1766 if (FLAG_debug_code) { | 1766 if (FLAG_debug_code) { |
| 1767 Register scratch = scratch0(); | 1767 Register scratch = scratch0(); |
| 1768 __ ld(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); | 1768 __ Ld(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 1769 __ lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 1769 __ Lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
| 1770 | 1770 |
| 1771 __ And(scratch, scratch, | 1771 __ And(scratch, scratch, |
| 1772 Operand(kStringRepresentationMask | kStringEncodingMask)); | 1772 Operand(kStringRepresentationMask | kStringEncodingMask)); |
| 1773 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; | 1773 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
| 1774 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 1774 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
| 1775 __ Dsubu(at, scratch, Operand(encoding == String::ONE_BYTE_ENCODING | 1775 __ Dsubu(at, scratch, Operand(encoding == String::ONE_BYTE_ENCODING |
| 1776 ? one_byte_seq_type : two_byte_seq_type)); | 1776 ? one_byte_seq_type : two_byte_seq_type)); |
| 1777 __ Check(eq, kUnexpectedStringType, at, Operand(zero_reg)); | 1777 __ Check(eq, kUnexpectedStringType, at, Operand(zero_reg)); |
| 1778 } | 1778 } |
| 1779 | 1779 |
| 1780 MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); | 1780 MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); |
| 1781 if (encoding == String::ONE_BYTE_ENCODING) { | 1781 if (encoding == String::ONE_BYTE_ENCODING) { |
| 1782 __ lbu(result, operand); | 1782 __ Lbu(result, operand); |
| 1783 } else { | 1783 } else { |
| 1784 __ lhu(result, operand); | 1784 __ Lhu(result, operand); |
| 1785 } | 1785 } |
| 1786 } | 1786 } |
| 1787 | 1787 |
| 1788 | 1788 |
| 1789 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { | 1789 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { |
| 1790 String::Encoding encoding = instr->hydrogen()->encoding(); | 1790 String::Encoding encoding = instr->hydrogen()->encoding(); |
| 1791 Register string = ToRegister(instr->string()); | 1791 Register string = ToRegister(instr->string()); |
| 1792 Register value = ToRegister(instr->value()); | 1792 Register value = ToRegister(instr->value()); |
| 1793 | 1793 |
| 1794 if (FLAG_debug_code) { | 1794 if (FLAG_debug_code) { |
| 1795 Register scratch = scratch0(); | 1795 Register scratch = scratch0(); |
| 1796 Register index = ToRegister(instr->index()); | 1796 Register index = ToRegister(instr->index()); |
| 1797 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; | 1797 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
| 1798 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 1798 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
| 1799 int encoding_mask = | 1799 int encoding_mask = |
| 1800 instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING | 1800 instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING |
| 1801 ? one_byte_seq_type : two_byte_seq_type; | 1801 ? one_byte_seq_type : two_byte_seq_type; |
| 1802 __ EmitSeqStringSetCharCheck(string, index, value, scratch, encoding_mask); | 1802 __ EmitSeqStringSetCharCheck(string, index, value, scratch, encoding_mask); |
| 1803 } | 1803 } |
| 1804 | 1804 |
| 1805 MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); | 1805 MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); |
| 1806 if (encoding == String::ONE_BYTE_ENCODING) { | 1806 if (encoding == String::ONE_BYTE_ENCODING) { |
| 1807 __ sb(value, operand); | 1807 __ Sb(value, operand); |
| 1808 } else { | 1808 } else { |
| 1809 __ sh(value, operand); | 1809 __ Sh(value, operand); |
| 1810 } | 1810 } |
| 1811 } | 1811 } |
| 1812 | 1812 |
| 1813 | 1813 |
| 1814 void LCodeGen::DoAddE(LAddE* instr) { | 1814 void LCodeGen::DoAddE(LAddE* instr) { |
| 1815 LOperand* result = instr->result(); | 1815 LOperand* result = instr->result(); |
| 1816 LOperand* left = instr->left(); | 1816 LOperand* left = instr->left(); |
| 1817 LOperand* right = instr->right(); | 1817 LOperand* right = instr->right(); |
| 1818 | 1818 |
| 1819 DCHECK(!instr->hydrogen()->CheckFlag(HValue::kCanOverflow)); | 1819 DCHECK(!instr->hydrogen()->CheckFlag(HValue::kCanOverflow)); |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2062 EmitBranch(instr, eq, reg, Operand(at)); | 2062 EmitBranch(instr, eq, reg, Operand(at)); |
| 2063 } else if (type.IsSmi()) { | 2063 } else if (type.IsSmi()) { |
| 2064 DCHECK(!info()->IsStub()); | 2064 DCHECK(!info()->IsStub()); |
| 2065 EmitBranch(instr, ne, reg, Operand(zero_reg)); | 2065 EmitBranch(instr, ne, reg, Operand(zero_reg)); |
| 2066 } else if (type.IsJSArray()) { | 2066 } else if (type.IsJSArray()) { |
| 2067 DCHECK(!info()->IsStub()); | 2067 DCHECK(!info()->IsStub()); |
| 2068 EmitBranch(instr, al, zero_reg, Operand(zero_reg)); | 2068 EmitBranch(instr, al, zero_reg, Operand(zero_reg)); |
| 2069 } else if (type.IsHeapNumber()) { | 2069 } else if (type.IsHeapNumber()) { |
| 2070 DCHECK(!info()->IsStub()); | 2070 DCHECK(!info()->IsStub()); |
| 2071 DoubleRegister dbl_scratch = double_scratch0(); | 2071 DoubleRegister dbl_scratch = double_scratch0(); |
| 2072 __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 2072 __ Ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
| 2073 // Test the double value. Zero and NaN are false. | 2073 // Test the double value. Zero and NaN are false. |
| 2074 EmitBranchF(instr, ogl, dbl_scratch, kDoubleRegZero); | 2074 EmitBranchF(instr, ogl, dbl_scratch, kDoubleRegZero); |
| 2075 } else if (type.IsString()) { | 2075 } else if (type.IsString()) { |
| 2076 DCHECK(!info()->IsStub()); | 2076 DCHECK(!info()->IsStub()); |
| 2077 __ ld(at, FieldMemOperand(reg, String::kLengthOffset)); | 2077 __ Ld(at, FieldMemOperand(reg, String::kLengthOffset)); |
| 2078 EmitBranch(instr, ne, at, Operand(zero_reg)); | 2078 EmitBranch(instr, ne, at, Operand(zero_reg)); |
| 2079 } else { | 2079 } else { |
| 2080 ToBooleanHints expected = instr->hydrogen()->expected_input_types(); | 2080 ToBooleanHints expected = instr->hydrogen()->expected_input_types(); |
| 2081 // Avoid deopts in the case where we've never executed this path before. | 2081 // Avoid deopts in the case where we've never executed this path before. |
| 2082 if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny; | 2082 if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny; |
| 2083 | 2083 |
| 2084 if (expected & ToBooleanHint::kUndefined) { | 2084 if (expected & ToBooleanHint::kUndefined) { |
| 2085 // undefined -> false. | 2085 // undefined -> false. |
| 2086 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 2086 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 2087 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at)); | 2087 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2104 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(zero_reg)); | 2104 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(zero_reg)); |
| 2105 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2105 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
| 2106 } else if (expected & ToBooleanHint::kNeedsMap) { | 2106 } else if (expected & ToBooleanHint::kNeedsMap) { |
| 2107 // If we need a map later and have a Smi -> deopt. | 2107 // If we need a map later and have a Smi -> deopt. |
| 2108 __ SmiTst(reg, at); | 2108 __ SmiTst(reg, at); |
| 2109 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, at, Operand(zero_reg)); | 2109 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, at, Operand(zero_reg)); |
| 2110 } | 2110 } |
| 2111 | 2111 |
| 2112 const Register map = scratch0(); | 2112 const Register map = scratch0(); |
| 2113 if (expected & ToBooleanHint::kNeedsMap) { | 2113 if (expected & ToBooleanHint::kNeedsMap) { |
| 2114 __ ld(map, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2114 __ Ld(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2115 if (expected & ToBooleanHint::kCanBeUndetectable) { | 2115 if (expected & ToBooleanHint::kCanBeUndetectable) { |
| 2116 // Undetectable -> false. | 2116 // Undetectable -> false. |
| 2117 __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset)); | 2117 __ Lbu(at, FieldMemOperand(map, Map::kBitFieldOffset)); |
| 2118 __ And(at, at, Operand(1 << Map::kIsUndetectable)); | 2118 __ And(at, at, Operand(1 << Map::kIsUndetectable)); |
| 2119 __ Branch(instr->FalseLabel(chunk_), ne, at, Operand(zero_reg)); | 2119 __ Branch(instr->FalseLabel(chunk_), ne, at, Operand(zero_reg)); |
| 2120 } | 2120 } |
| 2121 } | 2121 } |
| 2122 | 2122 |
| 2123 if (expected & ToBooleanHint::kReceiver) { | 2123 if (expected & ToBooleanHint::kReceiver) { |
| 2124 // spec object -> true. | 2124 // spec object -> true. |
| 2125 __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 2125 __ Lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 2126 __ Branch(instr->TrueLabel(chunk_), | 2126 __ Branch(instr->TrueLabel(chunk_), |
| 2127 ge, at, Operand(FIRST_JS_RECEIVER_TYPE)); | 2127 ge, at, Operand(FIRST_JS_RECEIVER_TYPE)); |
| 2128 } | 2128 } |
| 2129 | 2129 |
| 2130 if (expected & ToBooleanHint::kString) { | 2130 if (expected & ToBooleanHint::kString) { |
| 2131 // String value -> false iff empty. | 2131 // String value -> false iff empty. |
| 2132 Label not_string; | 2132 Label not_string; |
| 2133 __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 2133 __ Lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 2134 __ Branch(¬_string, ge , at, Operand(FIRST_NONSTRING_TYPE)); | 2134 __ Branch(¬_string, ge , at, Operand(FIRST_NONSTRING_TYPE)); |
| 2135 __ ld(at, FieldMemOperand(reg, String::kLengthOffset)); | 2135 __ Ld(at, FieldMemOperand(reg, String::kLengthOffset)); |
| 2136 __ Branch(instr->TrueLabel(chunk_), ne, at, Operand(zero_reg)); | 2136 __ Branch(instr->TrueLabel(chunk_), ne, at, Operand(zero_reg)); |
| 2137 __ Branch(instr->FalseLabel(chunk_)); | 2137 __ Branch(instr->FalseLabel(chunk_)); |
| 2138 __ bind(¬_string); | 2138 __ bind(¬_string); |
| 2139 } | 2139 } |
| 2140 | 2140 |
| 2141 if (expected & ToBooleanHint::kSymbol) { | 2141 if (expected & ToBooleanHint::kSymbol) { |
| 2142 // Symbol value -> true. | 2142 // Symbol value -> true. |
| 2143 const Register scratch = scratch1(); | 2143 const Register scratch = scratch1(); |
| 2144 __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 2144 __ Lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 2145 __ Branch(instr->TrueLabel(chunk_), eq, scratch, Operand(SYMBOL_TYPE)); | 2145 __ Branch(instr->TrueLabel(chunk_), eq, scratch, Operand(SYMBOL_TYPE)); |
| 2146 } | 2146 } |
| 2147 | 2147 |
| 2148 if (expected & ToBooleanHint::kHeapNumber) { | 2148 if (expected & ToBooleanHint::kHeapNumber) { |
| 2149 // heap number -> false iff +0, -0, or NaN. | 2149 // heap number -> false iff +0, -0, or NaN. |
| 2150 DoubleRegister dbl_scratch = double_scratch0(); | 2150 DoubleRegister dbl_scratch = double_scratch0(); |
| 2151 Label not_heap_number; | 2151 Label not_heap_number; |
| 2152 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 2152 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 2153 __ Branch(¬_heap_number, ne, map, Operand(at)); | 2153 __ Branch(¬_heap_number, ne, map, Operand(at)); |
| 2154 __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 2154 __ Ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
| 2155 __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), | 2155 __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
| 2156 ne, dbl_scratch, kDoubleRegZero); | 2156 ne, dbl_scratch, kDoubleRegZero); |
| 2157 // Falls through if dbl_scratch == 0. | 2157 // Falls through if dbl_scratch == 0. |
| 2158 __ Branch(instr->FalseLabel(chunk_)); | 2158 __ Branch(instr->FalseLabel(chunk_)); |
| 2159 __ bind(¬_heap_number); | 2159 __ bind(¬_heap_number); |
| 2160 } | 2160 } |
| 2161 | 2161 |
| 2162 if (expected != ToBooleanHint::kAny) { | 2162 if (expected != ToBooleanHint::kAny) { |
| 2163 // We've seen something for the first time -> deopt. | 2163 // We've seen something for the first time -> deopt. |
| 2164 // This can only happen if we are not generic already. | 2164 // This can only happen if we are not generic already. |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2338 } | 2338 } |
| 2339 | 2339 |
| 2340 | 2340 |
| 2341 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 2341 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
| 2342 Register input = ToRegister(instr->value()); | 2342 Register input = ToRegister(instr->value()); |
| 2343 Register temp = ToRegister(instr->temp()); | 2343 Register temp = ToRegister(instr->temp()); |
| 2344 | 2344 |
| 2345 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 2345 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
| 2346 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); | 2346 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
| 2347 } | 2347 } |
| 2348 __ ld(temp, FieldMemOperand(input, HeapObject::kMapOffset)); | 2348 __ Ld(temp, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 2349 __ lbu(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); | 2349 __ Lbu(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); |
| 2350 __ And(at, temp, Operand(1 << Map::kIsUndetectable)); | 2350 __ And(at, temp, Operand(1 << Map::kIsUndetectable)); |
| 2351 EmitBranch(instr, ne, at, Operand(zero_reg)); | 2351 EmitBranch(instr, ne, at, Operand(zero_reg)); |
| 2352 } | 2352 } |
| 2353 | 2353 |
| 2354 | 2354 |
| 2355 static Condition ComputeCompareCondition(Token::Value op) { | 2355 static Condition ComputeCompareCondition(Token::Value op) { |
| 2356 switch (op) { | 2356 switch (op) { |
| 2357 case Token::EQ_STRICT: | 2357 case Token::EQ_STRICT: |
| 2358 case Token::EQ: | 2358 case Token::EQ: |
| 2359 return eq; | 2359 return eq; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2446 | 2446 |
| 2447 // Objects with a non-function constructor have class 'Object'. | 2447 // Objects with a non-function constructor have class 'Object'. |
| 2448 if (String::Equals(class_name, isolate()->factory()->Object_string())) { | 2448 if (String::Equals(class_name, isolate()->factory()->Object_string())) { |
| 2449 __ Branch(is_true, ne, instance_type, Operand(JS_FUNCTION_TYPE)); | 2449 __ Branch(is_true, ne, instance_type, Operand(JS_FUNCTION_TYPE)); |
| 2450 } else { | 2450 } else { |
| 2451 __ Branch(is_false, ne, instance_type, Operand(JS_FUNCTION_TYPE)); | 2451 __ Branch(is_false, ne, instance_type, Operand(JS_FUNCTION_TYPE)); |
| 2452 } | 2452 } |
| 2453 | 2453 |
| 2454 // temp now contains the constructor function. Grab the | 2454 // temp now contains the constructor function. Grab the |
| 2455 // instance class name from there. | 2455 // instance class name from there. |
| 2456 __ ld(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset)); | 2456 __ Ld(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset)); |
| 2457 __ ld(temp, | 2457 __ Ld(temp, |
| 2458 FieldMemOperand(temp, SharedFunctionInfo::kInstanceClassNameOffset)); | 2458 FieldMemOperand(temp, SharedFunctionInfo::kInstanceClassNameOffset)); |
| 2459 // The class name we are testing against is internalized since it's a literal. | 2459 // The class name we are testing against is internalized since it's a literal. |
| 2460 // The name in the constructor is internalized because of the way the context | 2460 // The name in the constructor is internalized because of the way the context |
| 2461 // is booted. This routine isn't expected to work for random API-created | 2461 // is booted. This routine isn't expected to work for random API-created |
| 2462 // classes and it doesn't have to because you can't access it with natives | 2462 // classes and it doesn't have to because you can't access it with natives |
| 2463 // syntax. Since both sides are internalized it is sufficient to use an | 2463 // syntax. Since both sides are internalized it is sufficient to use an |
| 2464 // identity comparison. | 2464 // identity comparison. |
| 2465 | 2465 |
| 2466 // End with the address of this class_name instance in temp register. | 2466 // End with the address of this class_name instance in temp register. |
| 2467 // On MIPS, the caller must do the comparison with Handle<String>class_name. | 2467 // On MIPS, the caller must do the comparison with Handle<String>class_name. |
| 2468 } | 2468 } |
| 2469 | 2469 |
| 2470 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2470 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| 2471 Register input = ToRegister(instr->value()); | 2471 Register input = ToRegister(instr->value()); |
| 2472 Register temp = scratch0(); | 2472 Register temp = scratch0(); |
| 2473 Register temp2 = ToRegister(instr->temp()); | 2473 Register temp2 = ToRegister(instr->temp()); |
| 2474 Handle<String> class_name = instr->hydrogen()->class_name(); | 2474 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 2475 | 2475 |
| 2476 EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), | 2476 EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
| 2477 class_name, input, temp, temp2); | 2477 class_name, input, temp, temp2); |
| 2478 | 2478 |
| 2479 EmitBranch(instr, eq, temp, Operand(class_name)); | 2479 EmitBranch(instr, eq, temp, Operand(class_name)); |
| 2480 } | 2480 } |
| 2481 | 2481 |
| 2482 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2482 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
| 2483 Register reg = ToRegister(instr->value()); | 2483 Register reg = ToRegister(instr->value()); |
| 2484 Register temp = ToRegister(instr->temp()); | 2484 Register temp = ToRegister(instr->temp()); |
| 2485 | 2485 |
| 2486 __ ld(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2486 __ Ld(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2487 EmitBranch(instr, eq, temp, Operand(instr->map())); | 2487 EmitBranch(instr, eq, temp, Operand(instr->map())); |
| 2488 } | 2488 } |
| 2489 | 2489 |
| 2490 | 2490 |
| 2491 void LCodeGen::DoHasInPrototypeChainAndBranch( | 2491 void LCodeGen::DoHasInPrototypeChainAndBranch( |
| 2492 LHasInPrototypeChainAndBranch* instr) { | 2492 LHasInPrototypeChainAndBranch* instr) { |
| 2493 Register const object = ToRegister(instr->object()); | 2493 Register const object = ToRegister(instr->object()); |
| 2494 Register const object_map = scratch0(); | 2494 Register const object_map = scratch0(); |
| 2495 Register const object_instance_type = scratch1(); | 2495 Register const object_instance_type = scratch1(); |
| 2496 Register const object_prototype = object_map; | 2496 Register const object_prototype = object_map; |
| 2497 Register const prototype = ToRegister(instr->prototype()); | 2497 Register const prototype = ToRegister(instr->prototype()); |
| 2498 | 2498 |
| 2499 // The {object} must be a spec object. It's sufficient to know that {object} | 2499 // The {object} must be a spec object. It's sufficient to know that {object} |
| 2500 // is not a smi, since all other non-spec objects have {null} prototypes and | 2500 // is not a smi, since all other non-spec objects have {null} prototypes and |
| 2501 // will be ruled out below. | 2501 // will be ruled out below. |
| 2502 if (instr->hydrogen()->ObjectNeedsSmiCheck()) { | 2502 if (instr->hydrogen()->ObjectNeedsSmiCheck()) { |
| 2503 __ SmiTst(object, at); | 2503 __ SmiTst(object, at); |
| 2504 EmitFalseBranch(instr, eq, at, Operand(zero_reg)); | 2504 EmitFalseBranch(instr, eq, at, Operand(zero_reg)); |
| 2505 } | 2505 } |
| 2506 | 2506 |
| 2507 // Loop through the {object}s prototype chain looking for the {prototype}. | 2507 // Loop through the {object}s prototype chain looking for the {prototype}. |
| 2508 __ ld(object_map, FieldMemOperand(object, HeapObject::kMapOffset)); | 2508 __ Ld(object_map, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 2509 Label loop; | 2509 Label loop; |
| 2510 __ bind(&loop); | 2510 __ bind(&loop); |
| 2511 | 2511 |
| 2512 // Deoptimize if the object needs to be access checked. | 2512 // Deoptimize if the object needs to be access checked. |
| 2513 __ lbu(object_instance_type, | 2513 __ Lbu(object_instance_type, |
| 2514 FieldMemOperand(object_map, Map::kBitFieldOffset)); | 2514 FieldMemOperand(object_map, Map::kBitFieldOffset)); |
| 2515 __ And(object_instance_type, object_instance_type, | 2515 __ And(object_instance_type, object_instance_type, |
| 2516 Operand(1 << Map::kIsAccessCheckNeeded)); | 2516 Operand(1 << Map::kIsAccessCheckNeeded)); |
| 2517 DeoptimizeIf(ne, instr, DeoptimizeReason::kAccessCheck, object_instance_type, | 2517 DeoptimizeIf(ne, instr, DeoptimizeReason::kAccessCheck, object_instance_type, |
| 2518 Operand(zero_reg)); | 2518 Operand(zero_reg)); |
| 2519 __ lbu(object_instance_type, | 2519 __ Lbu(object_instance_type, |
| 2520 FieldMemOperand(object_map, Map::kInstanceTypeOffset)); | 2520 FieldMemOperand(object_map, Map::kInstanceTypeOffset)); |
| 2521 DeoptimizeIf(eq, instr, DeoptimizeReason::kProxy, object_instance_type, | 2521 DeoptimizeIf(eq, instr, DeoptimizeReason::kProxy, object_instance_type, |
| 2522 Operand(JS_PROXY_TYPE)); | 2522 Operand(JS_PROXY_TYPE)); |
| 2523 | 2523 |
| 2524 __ ld(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset)); | 2524 __ Ld(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset)); |
| 2525 __ LoadRoot(at, Heap::kNullValueRootIndex); | 2525 __ LoadRoot(at, Heap::kNullValueRootIndex); |
| 2526 EmitFalseBranch(instr, eq, object_prototype, Operand(at)); | 2526 EmitFalseBranch(instr, eq, object_prototype, Operand(at)); |
| 2527 EmitTrueBranch(instr, eq, object_prototype, Operand(prototype)); | 2527 EmitTrueBranch(instr, eq, object_prototype, Operand(prototype)); |
| 2528 __ Branch(&loop, USE_DELAY_SLOT); | 2528 __ Branch(&loop, USE_DELAY_SLOT); |
| 2529 __ ld(object_map, FieldMemOperand(object_prototype, | 2529 __ Ld(object_map, FieldMemOperand(object_prototype, |
| 2530 HeapObject::kMapOffset)); // In delay slot. | 2530 HeapObject::kMapOffset)); // In delay slot. |
| 2531 } | 2531 } |
| 2532 | 2532 |
| 2533 | 2533 |
| 2534 void LCodeGen::DoCmpT(LCmpT* instr) { | 2534 void LCodeGen::DoCmpT(LCmpT* instr) { |
| 2535 DCHECK(ToRegister(instr->context()).is(cp)); | 2535 DCHECK(ToRegister(instr->context()).is(cp)); |
| 2536 Token::Value op = instr->op(); | 2536 Token::Value op = instr->op(); |
| 2537 | 2537 |
| 2538 Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); | 2538 Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); |
| 2539 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2539 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2553 } | 2553 } |
| 2554 | 2554 |
| 2555 | 2555 |
| 2556 void LCodeGen::DoReturn(LReturn* instr) { | 2556 void LCodeGen::DoReturn(LReturn* instr) { |
| 2557 if (FLAG_trace && info()->IsOptimizing()) { | 2557 if (FLAG_trace && info()->IsOptimizing()) { |
| 2558 // Push the return value on the stack as the parameter. | 2558 // Push the return value on the stack as the parameter. |
| 2559 // Runtime::TraceExit returns its parameter in v0. We're leaving the code | 2559 // Runtime::TraceExit returns its parameter in v0. We're leaving the code |
| 2560 // managed by the register allocator and tearing down the frame, it's | 2560 // managed by the register allocator and tearing down the frame, it's |
| 2561 // safe to write to the context register. | 2561 // safe to write to the context register. |
| 2562 __ push(v0); | 2562 __ push(v0); |
| 2563 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2563 __ Ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2564 __ CallRuntime(Runtime::kTraceExit); | 2564 __ CallRuntime(Runtime::kTraceExit); |
| 2565 } | 2565 } |
| 2566 if (info()->saves_caller_doubles()) { | 2566 if (info()->saves_caller_doubles()) { |
| 2567 RestoreCallerDoubles(); | 2567 RestoreCallerDoubles(); |
| 2568 } | 2568 } |
| 2569 if (NeedsEagerFrame()) { | 2569 if (NeedsEagerFrame()) { |
| 2570 __ mov(sp, fp); | 2570 __ mov(sp, fp); |
| 2571 __ Pop(ra, fp); | 2571 __ Pop(ra, fp); |
| 2572 } | 2572 } |
| 2573 if (instr->has_constant_parameter_count()) { | 2573 if (instr->has_constant_parameter_count()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2585 } | 2585 } |
| 2586 | 2586 |
| 2587 __ Jump(ra); | 2587 __ Jump(ra); |
| 2588 } | 2588 } |
| 2589 | 2589 |
| 2590 | 2590 |
| 2591 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 2591 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
| 2592 Register context = ToRegister(instr->context()); | 2592 Register context = ToRegister(instr->context()); |
| 2593 Register result = ToRegister(instr->result()); | 2593 Register result = ToRegister(instr->result()); |
| 2594 | 2594 |
| 2595 __ ld(result, ContextMemOperand(context, instr->slot_index())); | 2595 __ Ld(result, ContextMemOperand(context, instr->slot_index())); |
| 2596 if (instr->hydrogen()->RequiresHoleCheck()) { | 2596 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2597 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2597 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2598 | 2598 |
| 2599 if (instr->hydrogen()->DeoptimizesOnHole()) { | 2599 if (instr->hydrogen()->DeoptimizesOnHole()) { |
| 2600 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, result, Operand(at)); | 2600 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, result, Operand(at)); |
| 2601 } else { | 2601 } else { |
| 2602 Label is_not_hole; | 2602 Label is_not_hole; |
| 2603 __ Branch(&is_not_hole, ne, result, Operand(at)); | 2603 __ Branch(&is_not_hole, ne, result, Operand(at)); |
| 2604 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); | 2604 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
| 2605 __ bind(&is_not_hole); | 2605 __ bind(&is_not_hole); |
| 2606 } | 2606 } |
| 2607 } | 2607 } |
| 2608 } | 2608 } |
| 2609 | 2609 |
| 2610 | 2610 |
| 2611 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 2611 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
| 2612 Register context = ToRegister(instr->context()); | 2612 Register context = ToRegister(instr->context()); |
| 2613 Register value = ToRegister(instr->value()); | 2613 Register value = ToRegister(instr->value()); |
| 2614 Register scratch = scratch0(); | 2614 Register scratch = scratch0(); |
| 2615 MemOperand target = ContextMemOperand(context, instr->slot_index()); | 2615 MemOperand target = ContextMemOperand(context, instr->slot_index()); |
| 2616 | 2616 |
| 2617 Label skip_assignment; | 2617 Label skip_assignment; |
| 2618 | 2618 |
| 2619 if (instr->hydrogen()->RequiresHoleCheck()) { | 2619 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2620 __ ld(scratch, target); | 2620 __ Ld(scratch, target); |
| 2621 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2621 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2622 | 2622 |
| 2623 if (instr->hydrogen()->DeoptimizesOnHole()) { | 2623 if (instr->hydrogen()->DeoptimizesOnHole()) { |
| 2624 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, scratch, Operand(at)); | 2624 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, scratch, Operand(at)); |
| 2625 } else { | 2625 } else { |
| 2626 __ Branch(&skip_assignment, ne, scratch, Operand(at)); | 2626 __ Branch(&skip_assignment, ne, scratch, Operand(at)); |
| 2627 } | 2627 } |
| 2628 } | 2628 } |
| 2629 | 2629 |
| 2630 __ sd(value, target); | 2630 __ Sd(value, target); |
| 2631 if (instr->hydrogen()->NeedsWriteBarrier()) { | 2631 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 2632 SmiCheck check_needed = | 2632 SmiCheck check_needed = |
| 2633 instr->hydrogen()->value()->type().IsHeapObject() | 2633 instr->hydrogen()->value()->type().IsHeapObject() |
| 2634 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 2634 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 2635 __ RecordWriteContextSlot(context, | 2635 __ RecordWriteContextSlot(context, |
| 2636 target.offset(), | 2636 target.offset(), |
| 2637 value, | 2637 value, |
| 2638 scratch0(), | 2638 scratch0(), |
| 2639 GetRAState(), | 2639 GetRAState(), |
| 2640 kSaveFPRegs, | 2640 kSaveFPRegs, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2652 Register object = ToRegister(instr->object()); | 2652 Register object = ToRegister(instr->object()); |
| 2653 if (access.IsExternalMemory()) { | 2653 if (access.IsExternalMemory()) { |
| 2654 Register result = ToRegister(instr->result()); | 2654 Register result = ToRegister(instr->result()); |
| 2655 MemOperand operand = MemOperand(object, offset); | 2655 MemOperand operand = MemOperand(object, offset); |
| 2656 __ Load(result, operand, access.representation()); | 2656 __ Load(result, operand, access.representation()); |
| 2657 return; | 2657 return; |
| 2658 } | 2658 } |
| 2659 | 2659 |
| 2660 if (instr->hydrogen()->representation().IsDouble()) { | 2660 if (instr->hydrogen()->representation().IsDouble()) { |
| 2661 DoubleRegister result = ToDoubleRegister(instr->result()); | 2661 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 2662 __ ldc1(result, FieldMemOperand(object, offset)); | 2662 __ Ldc1(result, FieldMemOperand(object, offset)); |
| 2663 return; | 2663 return; |
| 2664 } | 2664 } |
| 2665 | 2665 |
| 2666 Register result = ToRegister(instr->result()); | 2666 Register result = ToRegister(instr->result()); |
| 2667 if (!access.IsInobject()) { | 2667 if (!access.IsInobject()) { |
| 2668 __ ld(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 2668 __ Ld(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 2669 object = result; | 2669 object = result; |
| 2670 } | 2670 } |
| 2671 | 2671 |
| 2672 Representation representation = access.representation(); | 2672 Representation representation = access.representation(); |
| 2673 if (representation.IsSmi() && SmiValuesAre32Bits() && | 2673 if (representation.IsSmi() && SmiValuesAre32Bits() && |
| 2674 instr->hydrogen()->representation().IsInteger32()) { | 2674 instr->hydrogen()->representation().IsInteger32()) { |
| 2675 if (FLAG_debug_code) { | 2675 if (FLAG_debug_code) { |
| 2676 // Verify this is really an Smi. | 2676 // Verify this is really an Smi. |
| 2677 Register scratch = scratch0(); | 2677 Register scratch = scratch0(); |
| 2678 __ Load(scratch, FieldMemOperand(object, offset), representation); | 2678 __ Load(scratch, FieldMemOperand(object, offset), representation); |
| 2679 __ AssertSmi(scratch); | 2679 __ AssertSmi(scratch); |
| 2680 } | 2680 } |
| 2681 | 2681 |
| 2682 // Read int value directly from upper half of the smi. | 2682 // Read int value directly from upper half of the smi. |
| 2683 STATIC_ASSERT(kSmiTag == 0); | 2683 STATIC_ASSERT(kSmiTag == 0); |
| 2684 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 2684 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
| 2685 offset = SmiWordOffset(offset); | 2685 offset = SmiWordOffset(offset); |
| 2686 representation = Representation::Integer32(); | 2686 representation = Representation::Integer32(); |
| 2687 } | 2687 } |
| 2688 __ Load(result, FieldMemOperand(object, offset), representation); | 2688 __ Load(result, FieldMemOperand(object, offset), representation); |
| 2689 } | 2689 } |
| 2690 | 2690 |
| 2691 | 2691 |
| 2692 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 2692 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
| 2693 Register scratch = scratch0(); | 2693 Register scratch = scratch0(); |
| 2694 Register function = ToRegister(instr->function()); | 2694 Register function = ToRegister(instr->function()); |
| 2695 Register result = ToRegister(instr->result()); | 2695 Register result = ToRegister(instr->result()); |
| 2696 | 2696 |
| 2697 // Get the prototype or initial map from the function. | 2697 // Get the prototype or initial map from the function. |
| 2698 __ ld(result, | 2698 __ Ld(result, |
| 2699 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 2699 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 2700 | 2700 |
| 2701 // Check that the function has a prototype or an initial map. | 2701 // Check that the function has a prototype or an initial map. |
| 2702 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2702 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2703 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, result, Operand(at)); | 2703 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, result, Operand(at)); |
| 2704 | 2704 |
| 2705 // If the function does not have an initial map, we're done. | 2705 // If the function does not have an initial map, we're done. |
| 2706 Label done; | 2706 Label done; |
| 2707 __ GetObjectType(result, scratch, scratch); | 2707 __ GetObjectType(result, scratch, scratch); |
| 2708 __ Branch(&done, ne, scratch, Operand(MAP_TYPE)); | 2708 __ Branch(&done, ne, scratch, Operand(MAP_TYPE)); |
| 2709 | 2709 |
| 2710 // Get the prototype from the initial map. | 2710 // Get the prototype from the initial map. |
| 2711 __ ld(result, FieldMemOperand(result, Map::kPrototypeOffset)); | 2711 __ Ld(result, FieldMemOperand(result, Map::kPrototypeOffset)); |
| 2712 | 2712 |
| 2713 // All done. | 2713 // All done. |
| 2714 __ bind(&done); | 2714 __ bind(&done); |
| 2715 } | 2715 } |
| 2716 | 2716 |
| 2717 | 2717 |
| 2718 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { | 2718 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { |
| 2719 Register result = ToRegister(instr->result()); | 2719 Register result = ToRegister(instr->result()); |
| 2720 __ LoadRoot(result, instr->index()); | 2720 __ LoadRoot(result, instr->index()); |
| 2721 } | 2721 } |
| 2722 | 2722 |
| 2723 | 2723 |
| 2724 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 2724 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| 2725 Register arguments = ToRegister(instr->arguments()); | 2725 Register arguments = ToRegister(instr->arguments()); |
| 2726 Register result = ToRegister(instr->result()); | 2726 Register result = ToRegister(instr->result()); |
| 2727 // There are two words between the frame pointer and the last argument. | 2727 // There are two words between the frame pointer and the last argument. |
| 2728 // Subtracting from length accounts for one of them add one more. | 2728 // Subtracting from length accounts for one of them add one more. |
| 2729 if (instr->length()->IsConstantOperand()) { | 2729 if (instr->length()->IsConstantOperand()) { |
| 2730 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); | 2730 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); |
| 2731 if (instr->index()->IsConstantOperand()) { | 2731 if (instr->index()->IsConstantOperand()) { |
| 2732 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 2732 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 2733 int index = (const_length - const_index) + 1; | 2733 int index = (const_length - const_index) + 1; |
| 2734 __ ld(result, MemOperand(arguments, index * kPointerSize)); | 2734 __ Ld(result, MemOperand(arguments, index * kPointerSize)); |
| 2735 } else { | 2735 } else { |
| 2736 Register index = ToRegister(instr->index()); | 2736 Register index = ToRegister(instr->index()); |
| 2737 __ li(at, Operand(const_length + 1)); | 2737 __ li(at, Operand(const_length + 1)); |
| 2738 __ Dsubu(result, at, index); | 2738 __ Dsubu(result, at, index); |
| 2739 __ Dlsa(at, arguments, result, kPointerSizeLog2); | 2739 __ Dlsa(at, arguments, result, kPointerSizeLog2); |
| 2740 __ ld(result, MemOperand(at)); | 2740 __ Ld(result, MemOperand(at)); |
| 2741 } | 2741 } |
| 2742 } else if (instr->index()->IsConstantOperand()) { | 2742 } else if (instr->index()->IsConstantOperand()) { |
| 2743 Register length = ToRegister(instr->length()); | 2743 Register length = ToRegister(instr->length()); |
| 2744 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 2744 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 2745 int loc = const_index - 1; | 2745 int loc = const_index - 1; |
| 2746 if (loc != 0) { | 2746 if (loc != 0) { |
| 2747 __ Dsubu(result, length, Operand(loc)); | 2747 __ Dsubu(result, length, Operand(loc)); |
| 2748 __ Dlsa(at, arguments, result, kPointerSizeLog2); | 2748 __ Dlsa(at, arguments, result, kPointerSizeLog2); |
| 2749 __ ld(result, MemOperand(at)); | 2749 __ Ld(result, MemOperand(at)); |
| 2750 } else { | 2750 } else { |
| 2751 __ Dlsa(at, arguments, length, kPointerSizeLog2); | 2751 __ Dlsa(at, arguments, length, kPointerSizeLog2); |
| 2752 __ ld(result, MemOperand(at)); | 2752 __ Ld(result, MemOperand(at)); |
| 2753 } | 2753 } |
| 2754 } else { | 2754 } else { |
| 2755 Register length = ToRegister(instr->length()); | 2755 Register length = ToRegister(instr->length()); |
| 2756 Register index = ToRegister(instr->index()); | 2756 Register index = ToRegister(instr->index()); |
| 2757 __ Dsubu(result, length, index); | 2757 __ Dsubu(result, length, index); |
| 2758 __ Daddu(result, result, 1); | 2758 __ Daddu(result, result, 1); |
| 2759 __ Dlsa(at, arguments, result, kPointerSizeLog2); | 2759 __ Dlsa(at, arguments, result, kPointerSizeLog2); |
| 2760 __ ld(result, MemOperand(at)); | 2760 __ Ld(result, MemOperand(at)); |
| 2761 } | 2761 } |
| 2762 } | 2762 } |
| 2763 | 2763 |
| 2764 | 2764 |
| 2765 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { | 2765 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
| 2766 Register external_pointer = ToRegister(instr->elements()); | 2766 Register external_pointer = ToRegister(instr->elements()); |
| 2767 Register key = no_reg; | 2767 Register key = no_reg; |
| 2768 ElementsKind elements_kind = instr->elements_kind(); | 2768 ElementsKind elements_kind = instr->elements_kind(); |
| 2769 bool key_is_constant = instr->key()->IsConstantOperand(); | 2769 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 2770 int constant_key = 0; | 2770 int constant_key = 0; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2793 __ dsra32(scratch0(), key, 0); | 2793 __ dsra32(scratch0(), key, 0); |
| 2794 } else { | 2794 } else { |
| 2795 __ dsra(scratch0(), key, -shift_size); | 2795 __ dsra(scratch0(), key, -shift_size); |
| 2796 } | 2796 } |
| 2797 } else { | 2797 } else { |
| 2798 __ dsll(scratch0(), key, shift_size); | 2798 __ dsll(scratch0(), key, shift_size); |
| 2799 } | 2799 } |
| 2800 __ Daddu(scratch0(), scratch0(), external_pointer); | 2800 __ Daddu(scratch0(), scratch0(), external_pointer); |
| 2801 } | 2801 } |
| 2802 if (elements_kind == FLOAT32_ELEMENTS) { | 2802 if (elements_kind == FLOAT32_ELEMENTS) { |
| 2803 __ lwc1(result, MemOperand(scratch0(), base_offset)); | 2803 __ Lwc1(result, MemOperand(scratch0(), base_offset)); |
| 2804 __ cvt_d_s(result, result); | 2804 __ cvt_d_s(result, result); |
| 2805 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS | 2805 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
| 2806 __ ldc1(result, MemOperand(scratch0(), base_offset)); | 2806 __ Ldc1(result, MemOperand(scratch0(), base_offset)); |
| 2807 } | 2807 } |
| 2808 } else { | 2808 } else { |
| 2809 Register result = ToRegister(instr->result()); | 2809 Register result = ToRegister(instr->result()); |
| 2810 MemOperand mem_operand = PrepareKeyedOperand( | 2810 MemOperand mem_operand = PrepareKeyedOperand( |
| 2811 key, external_pointer, key_is_constant, constant_key, | 2811 key, external_pointer, key_is_constant, constant_key, |
| 2812 element_size_shift, shift_size, base_offset); | 2812 element_size_shift, shift_size, base_offset); |
| 2813 switch (elements_kind) { | 2813 switch (elements_kind) { |
| 2814 case INT8_ELEMENTS: | 2814 case INT8_ELEMENTS: |
| 2815 __ lb(result, mem_operand); | 2815 __ Lb(result, mem_operand); |
| 2816 break; | 2816 break; |
| 2817 case UINT8_ELEMENTS: | 2817 case UINT8_ELEMENTS: |
| 2818 case UINT8_CLAMPED_ELEMENTS: | 2818 case UINT8_CLAMPED_ELEMENTS: |
| 2819 __ lbu(result, mem_operand); | 2819 __ Lbu(result, mem_operand); |
| 2820 break; | 2820 break; |
| 2821 case INT16_ELEMENTS: | 2821 case INT16_ELEMENTS: |
| 2822 __ lh(result, mem_operand); | 2822 __ Lh(result, mem_operand); |
| 2823 break; | 2823 break; |
| 2824 case UINT16_ELEMENTS: | 2824 case UINT16_ELEMENTS: |
| 2825 __ lhu(result, mem_operand); | 2825 __ Lhu(result, mem_operand); |
| 2826 break; | 2826 break; |
| 2827 case INT32_ELEMENTS: | 2827 case INT32_ELEMENTS: |
| 2828 __ lw(result, mem_operand); | 2828 __ Lw(result, mem_operand); |
| 2829 break; | 2829 break; |
| 2830 case UINT32_ELEMENTS: | 2830 case UINT32_ELEMENTS: |
| 2831 __ lw(result, mem_operand); | 2831 __ Lw(result, mem_operand); |
| 2832 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 2832 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| 2833 DeoptimizeIf(Ugreater_equal, instr, DeoptimizeReason::kNegativeValue, | 2833 DeoptimizeIf(Ugreater_equal, instr, DeoptimizeReason::kNegativeValue, |
| 2834 result, Operand(0x80000000)); | 2834 result, Operand(0x80000000)); |
| 2835 } | 2835 } |
| 2836 break; | 2836 break; |
| 2837 case FLOAT32_ELEMENTS: | 2837 case FLOAT32_ELEMENTS: |
| 2838 case FLOAT64_ELEMENTS: | 2838 case FLOAT64_ELEMENTS: |
| 2839 case FAST_DOUBLE_ELEMENTS: | 2839 case FAST_DOUBLE_ELEMENTS: |
| 2840 case FAST_ELEMENTS: | 2840 case FAST_ELEMENTS: |
| 2841 case FAST_SMI_ELEMENTS: | 2841 case FAST_SMI_ELEMENTS: |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2882 if (shift_size > 0) { | 2882 if (shift_size > 0) { |
| 2883 __ dsll(at, key, shift_size); | 2883 __ dsll(at, key, shift_size); |
| 2884 } else if (shift_size == -32) { | 2884 } else if (shift_size == -32) { |
| 2885 __ dsra32(at, key, 0); | 2885 __ dsra32(at, key, 0); |
| 2886 } else { | 2886 } else { |
| 2887 __ dsra(at, key, -shift_size); | 2887 __ dsra(at, key, -shift_size); |
| 2888 } | 2888 } |
| 2889 __ Daddu(scratch, scratch, at); | 2889 __ Daddu(scratch, scratch, at); |
| 2890 } | 2890 } |
| 2891 | 2891 |
| 2892 __ ldc1(result, MemOperand(scratch)); | 2892 __ Ldc1(result, MemOperand(scratch)); |
| 2893 | 2893 |
| 2894 if (instr->hydrogen()->RequiresHoleCheck()) { | 2894 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2895 __ FmoveHigh(scratch, result); | 2895 __ FmoveHigh(scratch, result); |
| 2896 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, scratch, | 2896 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, scratch, |
| 2897 Operand(static_cast<int32_t>(kHoleNanUpper32))); | 2897 Operand(static_cast<int32_t>(kHoleNanUpper32))); |
| 2898 } | 2898 } |
| 2899 } | 2899 } |
| 2900 | 2900 |
| 2901 | 2901 |
| 2902 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 2902 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2958 DCHECK(instr->hydrogen()->elements_kind() == FAST_HOLEY_ELEMENTS); | 2958 DCHECK(instr->hydrogen()->elements_kind() == FAST_HOLEY_ELEMENTS); |
| 2959 Label done; | 2959 Label done; |
| 2960 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | 2960 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
| 2961 __ Branch(&done, ne, result, Operand(scratch)); | 2961 __ Branch(&done, ne, result, Operand(scratch)); |
| 2962 if (info()->IsStub()) { | 2962 if (info()->IsStub()) { |
| 2963 // A stub can safely convert the hole to undefined only if the array | 2963 // A stub can safely convert the hole to undefined only if the array |
| 2964 // protector cell contains (Smi) Isolate::kProtectorValid. Otherwise | 2964 // protector cell contains (Smi) Isolate::kProtectorValid. Otherwise |
| 2965 // it needs to bail out. | 2965 // it needs to bail out. |
| 2966 __ LoadRoot(result, Heap::kArrayProtectorRootIndex); | 2966 __ LoadRoot(result, Heap::kArrayProtectorRootIndex); |
| 2967 // The comparison only needs LS bits of value, which is a smi. | 2967 // The comparison only needs LS bits of value, which is a smi. |
| 2968 __ ld(result, FieldMemOperand(result, PropertyCell::kValueOffset)); | 2968 __ Ld(result, FieldMemOperand(result, PropertyCell::kValueOffset)); |
| 2969 DeoptimizeIf(ne, instr, DeoptimizeReason::kHole, result, | 2969 DeoptimizeIf(ne, instr, DeoptimizeReason::kHole, result, |
| 2970 Operand(Smi::FromInt(Isolate::kProtectorValid))); | 2970 Operand(Smi::FromInt(Isolate::kProtectorValid))); |
| 2971 } | 2971 } |
| 2972 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); | 2972 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
| 2973 __ bind(&done); | 2973 __ bind(&done); |
| 2974 } | 2974 } |
| 2975 } | 2975 } |
| 2976 | 2976 |
| 2977 | 2977 |
| 2978 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { | 2978 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3032 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 3032 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
| 3033 Register scratch = scratch0(); | 3033 Register scratch = scratch0(); |
| 3034 Register temp = scratch1(); | 3034 Register temp = scratch1(); |
| 3035 Register result = ToRegister(instr->result()); | 3035 Register result = ToRegister(instr->result()); |
| 3036 | 3036 |
| 3037 if (instr->hydrogen()->from_inlined()) { | 3037 if (instr->hydrogen()->from_inlined()) { |
| 3038 __ Dsubu(result, sp, 2 * kPointerSize); | 3038 __ Dsubu(result, sp, 2 * kPointerSize); |
| 3039 } else if (instr->hydrogen()->arguments_adaptor()) { | 3039 } else if (instr->hydrogen()->arguments_adaptor()) { |
| 3040 // Check if the calling frame is an arguments adaptor frame. | 3040 // Check if the calling frame is an arguments adaptor frame. |
| 3041 Label done, adapted; | 3041 Label done, adapted; |
| 3042 __ ld(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 3042 __ Ld(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 3043 __ ld(result, | 3043 __ Ld(result, |
| 3044 MemOperand(scratch, CommonFrameConstants::kContextOrFrameTypeOffset)); | 3044 MemOperand(scratch, CommonFrameConstants::kContextOrFrameTypeOffset)); |
| 3045 __ Xor(temp, result, | 3045 __ Xor(temp, result, |
| 3046 Operand(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR))); | 3046 Operand(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR))); |
| 3047 | 3047 |
| 3048 // Result is the frame pointer for the frame if not adapted and for the real | 3048 // Result is the frame pointer for the frame if not adapted and for the real |
| 3049 // frame below the adaptor frame if adapted. | 3049 // frame below the adaptor frame if adapted. |
| 3050 __ Movn(result, fp, temp); // Move only if temp is not equal to zero (ne). | 3050 __ Movn(result, fp, temp); // Move only if temp is not equal to zero (ne). |
| 3051 __ Movz(result, scratch, temp); // Move only if temp is equal to zero (eq). | 3051 __ Movz(result, scratch, temp); // Move only if temp is equal to zero (eq). |
| 3052 } else { | 3052 } else { |
| 3053 __ mov(result, fp); | 3053 __ mov(result, fp); |
| 3054 } | 3054 } |
| 3055 } | 3055 } |
| 3056 | 3056 |
| 3057 | 3057 |
| 3058 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 3058 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
| 3059 Register elem = ToRegister(instr->elements()); | 3059 Register elem = ToRegister(instr->elements()); |
| 3060 Register result = ToRegister(instr->result()); | 3060 Register result = ToRegister(instr->result()); |
| 3061 | 3061 |
| 3062 Label done; | 3062 Label done; |
| 3063 | 3063 |
| 3064 // If no arguments adaptor frame the number of arguments is fixed. | 3064 // If no arguments adaptor frame the number of arguments is fixed. |
| 3065 __ Daddu(result, zero_reg, Operand(scope()->num_parameters())); | 3065 __ Daddu(result, zero_reg, Operand(scope()->num_parameters())); |
| 3066 __ Branch(&done, eq, fp, Operand(elem)); | 3066 __ Branch(&done, eq, fp, Operand(elem)); |
| 3067 | 3067 |
| 3068 // Arguments adaptor frame present. Get argument length from there. | 3068 // Arguments adaptor frame present. Get argument length from there. |
| 3069 __ ld(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 3069 __ Ld(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 3070 __ ld(result, | 3070 __ Ld(result, |
| 3071 MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 3071 MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 3072 __ SmiUntag(result); | 3072 __ SmiUntag(result); |
| 3073 | 3073 |
| 3074 // Argument length is in result register. | 3074 // Argument length is in result register. |
| 3075 __ bind(&done); | 3075 __ bind(&done); |
| 3076 } | 3076 } |
| 3077 | 3077 |
| 3078 | 3078 |
| 3079 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { | 3079 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
| 3080 Register receiver = ToRegister(instr->receiver()); | 3080 Register receiver = ToRegister(instr->receiver()); |
| 3081 Register function = ToRegister(instr->function()); | 3081 Register function = ToRegister(instr->function()); |
| 3082 Register result = ToRegister(instr->result()); | 3082 Register result = ToRegister(instr->result()); |
| 3083 Register scratch = scratch0(); | 3083 Register scratch = scratch0(); |
| 3084 | 3084 |
| 3085 // If the receiver is null or undefined, we have to pass the global | 3085 // If the receiver is null or undefined, we have to pass the global |
| 3086 // object as a receiver to normal functions. Values have to be | 3086 // object as a receiver to normal functions. Values have to be |
| 3087 // passed unchanged to builtins and strict-mode functions. | 3087 // passed unchanged to builtins and strict-mode functions. |
| 3088 Label global_object, result_in_receiver; | 3088 Label global_object, result_in_receiver; |
| 3089 | 3089 |
| 3090 if (!instr->hydrogen()->known_function()) { | 3090 if (!instr->hydrogen()->known_function()) { |
| 3091 // Do not transform the receiver to object for strict mode functions. | 3091 // Do not transform the receiver to object for strict mode functions. |
| 3092 __ ld(scratch, | 3092 __ Ld(scratch, |
| 3093 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 3093 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
| 3094 | 3094 |
| 3095 // Do not transform the receiver to object for builtins. | 3095 // Do not transform the receiver to object for builtins. |
| 3096 int32_t strict_mode_function_mask = | 3096 int32_t strict_mode_function_mask = |
| 3097 1 << SharedFunctionInfo::kStrictModeBitWithinByte; | 3097 1 << SharedFunctionInfo::kStrictModeBitWithinByte; |
| 3098 int32_t native_mask = 1 << SharedFunctionInfo::kNativeBitWithinByte; | 3098 int32_t native_mask = 1 << SharedFunctionInfo::kNativeBitWithinByte; |
| 3099 | 3099 |
| 3100 __ lbu(at, | 3100 __ Lbu(at, |
| 3101 FieldMemOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset)); | 3101 FieldMemOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset)); |
| 3102 __ And(at, at, Operand(strict_mode_function_mask)); | 3102 __ And(at, at, Operand(strict_mode_function_mask)); |
| 3103 __ Branch(&result_in_receiver, ne, at, Operand(zero_reg)); | 3103 __ Branch(&result_in_receiver, ne, at, Operand(zero_reg)); |
| 3104 __ lbu(at, | 3104 __ Lbu(at, FieldMemOperand(scratch, SharedFunctionInfo::kNativeByteOffset)); |
| 3105 FieldMemOperand(scratch, SharedFunctionInfo::kNativeByteOffset)); | |
| 3106 __ And(at, at, Operand(native_mask)); | 3105 __ And(at, at, Operand(native_mask)); |
| 3107 __ Branch(&result_in_receiver, ne, at, Operand(zero_reg)); | 3106 __ Branch(&result_in_receiver, ne, at, Operand(zero_reg)); |
| 3108 } | 3107 } |
| 3109 | 3108 |
| 3110 // Normal function. Replace undefined or null with global receiver. | 3109 // Normal function. Replace undefined or null with global receiver. |
| 3111 __ LoadRoot(scratch, Heap::kNullValueRootIndex); | 3110 __ LoadRoot(scratch, Heap::kNullValueRootIndex); |
| 3112 __ Branch(&global_object, eq, receiver, Operand(scratch)); | 3111 __ Branch(&global_object, eq, receiver, Operand(scratch)); |
| 3113 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); | 3112 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
| 3114 __ Branch(&global_object, eq, receiver, Operand(scratch)); | 3113 __ Branch(&global_object, eq, receiver, Operand(scratch)); |
| 3115 | 3114 |
| 3116 // Deoptimize if the receiver is not a JS object. | 3115 // Deoptimize if the receiver is not a JS object. |
| 3117 __ SmiTst(receiver, scratch); | 3116 __ SmiTst(receiver, scratch); |
| 3118 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, scratch, Operand(zero_reg)); | 3117 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, scratch, Operand(zero_reg)); |
| 3119 | 3118 |
| 3120 __ GetObjectType(receiver, scratch, scratch); | 3119 __ GetObjectType(receiver, scratch, scratch); |
| 3121 DeoptimizeIf(lt, instr, DeoptimizeReason::kNotAJavaScriptObject, scratch, | 3120 DeoptimizeIf(lt, instr, DeoptimizeReason::kNotAJavaScriptObject, scratch, |
| 3122 Operand(FIRST_JS_RECEIVER_TYPE)); | 3121 Operand(FIRST_JS_RECEIVER_TYPE)); |
| 3123 __ Branch(&result_in_receiver); | 3122 __ Branch(&result_in_receiver); |
| 3124 | 3123 |
| 3125 __ bind(&global_object); | 3124 __ bind(&global_object); |
| 3126 __ ld(result, FieldMemOperand(function, JSFunction::kContextOffset)); | 3125 __ Ld(result, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 3127 __ ld(result, ContextMemOperand(result, Context::NATIVE_CONTEXT_INDEX)); | 3126 __ Ld(result, ContextMemOperand(result, Context::NATIVE_CONTEXT_INDEX)); |
| 3128 __ ld(result, ContextMemOperand(result, Context::GLOBAL_PROXY_INDEX)); | 3127 __ Ld(result, ContextMemOperand(result, Context::GLOBAL_PROXY_INDEX)); |
| 3129 | 3128 |
| 3130 if (result.is(receiver)) { | 3129 if (result.is(receiver)) { |
| 3131 __ bind(&result_in_receiver); | 3130 __ bind(&result_in_receiver); |
| 3132 } else { | 3131 } else { |
| 3133 Label result_ok; | 3132 Label result_ok; |
| 3134 __ Branch(&result_ok); | 3133 __ Branch(&result_ok); |
| 3135 __ bind(&result_in_receiver); | 3134 __ bind(&result_in_receiver); |
| 3136 __ mov(result, receiver); | 3135 __ mov(result, receiver); |
| 3137 __ bind(&result_ok); | 3136 __ bind(&result_ok); |
| 3138 } | 3137 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3163 __ Daddu(elements, elements, Operand(1 * kPointerSize)); | 3162 __ Daddu(elements, elements, Operand(1 * kPointerSize)); |
| 3164 | 3163 |
| 3165 // Loop through the arguments pushing them onto the execution | 3164 // Loop through the arguments pushing them onto the execution |
| 3166 // stack. | 3165 // stack. |
| 3167 Label invoke, loop; | 3166 Label invoke, loop; |
| 3168 // length is a small non-negative integer, due to the test above. | 3167 // length is a small non-negative integer, due to the test above. |
| 3169 __ Branch(USE_DELAY_SLOT, &invoke, eq, length, Operand(zero_reg)); | 3168 __ Branch(USE_DELAY_SLOT, &invoke, eq, length, Operand(zero_reg)); |
| 3170 __ dsll(scratch, length, kPointerSizeLog2); | 3169 __ dsll(scratch, length, kPointerSizeLog2); |
| 3171 __ bind(&loop); | 3170 __ bind(&loop); |
| 3172 __ Daddu(scratch, elements, scratch); | 3171 __ Daddu(scratch, elements, scratch); |
| 3173 __ ld(scratch, MemOperand(scratch)); | 3172 __ Ld(scratch, MemOperand(scratch)); |
| 3174 __ push(scratch); | 3173 __ push(scratch); |
| 3175 __ Dsubu(length, length, Operand(1)); | 3174 __ Dsubu(length, length, Operand(1)); |
| 3176 __ Branch(USE_DELAY_SLOT, &loop, ne, length, Operand(zero_reg)); | 3175 __ Branch(USE_DELAY_SLOT, &loop, ne, length, Operand(zero_reg)); |
| 3177 __ dsll(scratch, length, kPointerSizeLog2); | 3176 __ dsll(scratch, length, kPointerSizeLog2); |
| 3178 | 3177 |
| 3179 __ bind(&invoke); | 3178 __ bind(&invoke); |
| 3180 | 3179 |
| 3181 InvokeFlag flag = CALL_FUNCTION; | 3180 InvokeFlag flag = CALL_FUNCTION; |
| 3182 if (instr->hydrogen()->tail_call_mode() == TailCallMode::kAllow) { | 3181 if (instr->hydrogen()->tail_call_mode() == TailCallMode::kAllow) { |
| 3183 DCHECK(!info()->saves_caller_doubles()); | 3182 DCHECK(!info()->saves_caller_doubles()); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3210 } | 3209 } |
| 3211 | 3210 |
| 3212 | 3211 |
| 3213 void LCodeGen::DoDrop(LDrop* instr) { | 3212 void LCodeGen::DoDrop(LDrop* instr) { |
| 3214 __ Drop(instr->count()); | 3213 __ Drop(instr->count()); |
| 3215 } | 3214 } |
| 3216 | 3215 |
| 3217 | 3216 |
| 3218 void LCodeGen::DoThisFunction(LThisFunction* instr) { | 3217 void LCodeGen::DoThisFunction(LThisFunction* instr) { |
| 3219 Register result = ToRegister(instr->result()); | 3218 Register result = ToRegister(instr->result()); |
| 3220 __ ld(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 3219 __ Ld(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 3221 } | 3220 } |
| 3222 | 3221 |
| 3223 | 3222 |
| 3224 void LCodeGen::DoContext(LContext* instr) { | 3223 void LCodeGen::DoContext(LContext* instr) { |
| 3225 // If there is a non-return use, the context must be moved to a register. | 3224 // If there is a non-return use, the context must be moved to a register. |
| 3226 Register result = ToRegister(instr->result()); | 3225 Register result = ToRegister(instr->result()); |
| 3227 if (info()->IsOptimizing()) { | 3226 if (info()->IsOptimizing()) { |
| 3228 __ ld(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3227 __ Ld(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 3229 } else { | 3228 } else { |
| 3230 // If there is no frame, the context must be in cp. | 3229 // If there is no frame, the context must be in cp. |
| 3231 DCHECK(result.is(cp)); | 3230 DCHECK(result.is(cp)); |
| 3232 } | 3231 } |
| 3233 } | 3232 } |
| 3234 | 3233 |
| 3235 | 3234 |
| 3236 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3235 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
| 3237 DCHECK(ToRegister(instr->context()).is(cp)); | 3236 DCHECK(ToRegister(instr->context()).is(cp)); |
| 3238 __ li(scratch0(), instr->hydrogen()->declarations()); | 3237 __ li(scratch0(), instr->hydrogen()->declarations()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3249 bool dont_adapt_arguments = | 3248 bool dont_adapt_arguments = |
| 3250 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3249 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 3251 bool can_invoke_directly = | 3250 bool can_invoke_directly = |
| 3252 dont_adapt_arguments || formal_parameter_count == arity; | 3251 dont_adapt_arguments || formal_parameter_count == arity; |
| 3253 | 3252 |
| 3254 Register function_reg = a1; | 3253 Register function_reg = a1; |
| 3255 LPointerMap* pointers = instr->pointer_map(); | 3254 LPointerMap* pointers = instr->pointer_map(); |
| 3256 | 3255 |
| 3257 if (can_invoke_directly) { | 3256 if (can_invoke_directly) { |
| 3258 // Change context. | 3257 // Change context. |
| 3259 __ ld(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); | 3258 __ Ld(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); |
| 3260 | 3259 |
| 3261 // Always initialize new target and number of actual arguments. | 3260 // Always initialize new target and number of actual arguments. |
| 3262 __ LoadRoot(a3, Heap::kUndefinedValueRootIndex); | 3261 __ LoadRoot(a3, Heap::kUndefinedValueRootIndex); |
| 3263 __ li(a0, Operand(arity)); | 3262 __ li(a0, Operand(arity)); |
| 3264 | 3263 |
| 3265 bool is_self_call = function.is_identical_to(info()->closure()); | 3264 bool is_self_call = function.is_identical_to(info()->closure()); |
| 3266 | 3265 |
| 3267 // Invoke function. | 3266 // Invoke function. |
| 3268 if (is_self_call) { | 3267 if (is_self_call) { |
| 3269 Handle<Code> self(reinterpret_cast<Code**>(__ CodeObject().location())); | 3268 Handle<Code> self(reinterpret_cast<Code**>(__ CodeObject().location())); |
| 3270 if (is_tail_call) { | 3269 if (is_tail_call) { |
| 3271 __ Jump(self, RelocInfo::CODE_TARGET); | 3270 __ Jump(self, RelocInfo::CODE_TARGET); |
| 3272 } else { | 3271 } else { |
| 3273 __ Call(self, RelocInfo::CODE_TARGET); | 3272 __ Call(self, RelocInfo::CODE_TARGET); |
| 3274 } | 3273 } |
| 3275 } else { | 3274 } else { |
| 3276 __ ld(at, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); | 3275 __ Ld(at, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); |
| 3277 if (is_tail_call) { | 3276 if (is_tail_call) { |
| 3278 __ Jump(at); | 3277 __ Jump(at); |
| 3279 } else { | 3278 } else { |
| 3280 __ Call(at); | 3279 __ Call(at); |
| 3281 } | 3280 } |
| 3282 } | 3281 } |
| 3283 | 3282 |
| 3284 if (!is_tail_call) { | 3283 if (!is_tail_call) { |
| 3285 // Set up deoptimization. | 3284 // Set up deoptimization. |
| 3286 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3285 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 3287 } | 3286 } |
| 3288 } else { | 3287 } else { |
| 3289 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3288 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3290 ParameterCount actual(arity); | 3289 ParameterCount actual(arity); |
| 3291 ParameterCount expected(formal_parameter_count); | 3290 ParameterCount expected(formal_parameter_count); |
| 3292 InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION; | 3291 InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION; |
| 3293 __ InvokeFunction(function_reg, expected, actual, flag, generator); | 3292 __ InvokeFunction(function_reg, expected, actual, flag, generator); |
| 3294 } | 3293 } |
| 3295 } | 3294 } |
| 3296 | 3295 |
| 3297 | 3296 |
| 3298 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3297 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3299 DCHECK(instr->context() != NULL); | 3298 DCHECK(instr->context() != NULL); |
| 3300 DCHECK(ToRegister(instr->context()).is(cp)); | 3299 DCHECK(ToRegister(instr->context()).is(cp)); |
| 3301 Register input = ToRegister(instr->value()); | 3300 Register input = ToRegister(instr->value()); |
| 3302 Register result = ToRegister(instr->result()); | 3301 Register result = ToRegister(instr->result()); |
| 3303 Register scratch = scratch0(); | 3302 Register scratch = scratch0(); |
| 3304 | 3303 |
| 3305 // Deoptimize if not a heap number. | 3304 // Deoptimize if not a heap number. |
| 3306 __ ld(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 3305 __ Ld(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 3307 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 3306 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 3308 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch, | 3307 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch, |
| 3309 Operand(at)); | 3308 Operand(at)); |
| 3310 | 3309 |
| 3311 Label done; | 3310 Label done; |
| 3312 Register exponent = scratch0(); | 3311 Register exponent = scratch0(); |
| 3313 scratch = no_reg; | 3312 scratch = no_reg; |
| 3314 __ lwu(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 3313 __ Lwu(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
| 3315 // Check the sign of the argument. If the argument is positive, just | 3314 // Check the sign of the argument. If the argument is positive, just |
| 3316 // return it. | 3315 // return it. |
| 3317 __ Move(result, input); | 3316 __ Move(result, input); |
| 3318 __ And(at, exponent, Operand(HeapNumber::kSignMask)); | 3317 __ And(at, exponent, Operand(HeapNumber::kSignMask)); |
| 3319 __ Branch(&done, eq, at, Operand(zero_reg)); | 3318 __ Branch(&done, eq, at, Operand(zero_reg)); |
| 3320 | 3319 |
| 3321 // Input is negative. Reverse its sign. | 3320 // Input is negative. Reverse its sign. |
| 3322 // Preserve the value of all registers. | 3321 // Preserve the value of all registers. |
| 3323 { | 3322 { |
| 3324 PushSafepointRegistersScope scope(this); | 3323 PushSafepointRegistersScope scope(this); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3340 // Slow case: Call the runtime system to do the number allocation. | 3339 // Slow case: Call the runtime system to do the number allocation. |
| 3341 __ bind(&slow); | 3340 __ bind(&slow); |
| 3342 | 3341 |
| 3343 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr, | 3342 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr, |
| 3344 instr->context()); | 3343 instr->context()); |
| 3345 // Set the pointer to the new heap number in tmp. | 3344 // Set the pointer to the new heap number in tmp. |
| 3346 if (!tmp1.is(v0)) | 3345 if (!tmp1.is(v0)) |
| 3347 __ mov(tmp1, v0); | 3346 __ mov(tmp1, v0); |
| 3348 // Restore input_reg after call to runtime. | 3347 // Restore input_reg after call to runtime. |
| 3349 __ LoadFromSafepointRegisterSlot(input, input); | 3348 __ LoadFromSafepointRegisterSlot(input, input); |
| 3350 __ lwu(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 3349 __ Lwu(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
| 3351 | 3350 |
| 3352 __ bind(&allocated); | 3351 __ bind(&allocated); |
| 3353 // exponent: floating point exponent value. | 3352 // exponent: floating point exponent value. |
| 3354 // tmp1: allocated heap number. | 3353 // tmp1: allocated heap number. |
| 3355 __ And(exponent, exponent, Operand(~HeapNumber::kSignMask)); | 3354 __ And(exponent, exponent, Operand(~HeapNumber::kSignMask)); |
| 3356 __ sw(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); | 3355 __ Sw(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); |
| 3357 __ lwu(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); | 3356 __ Lwu(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); |
| 3358 __ sw(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); | 3357 __ Sw(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); |
| 3359 | 3358 |
| 3360 __ StoreToSafepointRegisterSlot(tmp1, result); | 3359 __ StoreToSafepointRegisterSlot(tmp1, result); |
| 3361 } | 3360 } |
| 3362 | 3361 |
| 3363 __ bind(&done); | 3362 __ bind(&done); |
| 3364 } | 3363 } |
| 3365 | 3364 |
| 3366 | 3365 |
| 3367 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { | 3366 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { |
| 3368 Register input = ToRegister(instr->value()); | 3367 Register input = ToRegister(instr->value()); |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3594 DCHECK(ToDoubleRegister(instr->left()).is(f2)); | 3593 DCHECK(ToDoubleRegister(instr->left()).is(f2)); |
| 3595 DCHECK(ToDoubleRegister(instr->result()).is(f0)); | 3594 DCHECK(ToDoubleRegister(instr->result()).is(f0)); |
| 3596 | 3595 |
| 3597 if (exponent_type.IsSmi()) { | 3596 if (exponent_type.IsSmi()) { |
| 3598 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3597 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
| 3599 __ CallStub(&stub); | 3598 __ CallStub(&stub); |
| 3600 } else if (exponent_type.IsTagged()) { | 3599 } else if (exponent_type.IsTagged()) { |
| 3601 Label no_deopt; | 3600 Label no_deopt; |
| 3602 __ JumpIfSmi(tagged_exponent, &no_deopt); | 3601 __ JumpIfSmi(tagged_exponent, &no_deopt); |
| 3603 DCHECK(!a7.is(tagged_exponent)); | 3602 DCHECK(!a7.is(tagged_exponent)); |
| 3604 __ lw(a7, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); | 3603 __ Lw(a7, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); |
| 3605 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 3604 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 3606 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, a7, Operand(at)); | 3605 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, a7, Operand(at)); |
| 3607 __ bind(&no_deopt); | 3606 __ bind(&no_deopt); |
| 3608 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3607 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
| 3609 __ CallStub(&stub); | 3608 __ CallStub(&stub); |
| 3610 } else if (exponent_type.IsInteger32()) { | 3609 } else if (exponent_type.IsInteger32()) { |
| 3611 MathPowStub stub(isolate(), MathPowStub::INTEGER); | 3610 MathPowStub stub(isolate(), MathPowStub::INTEGER); |
| 3612 __ CallStub(&stub); | 3611 __ CallStub(&stub); |
| 3613 } else { | 3612 } else { |
| 3614 DCHECK(exponent_type.IsDouble()); | 3613 DCHECK(exponent_type.IsDouble()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3669 RegisterConfiguration::Crankshaft()->GetGeneralRegisterName( | 3668 RegisterConfiguration::Crankshaft()->GetGeneralRegisterName( |
| 3670 actual.reg().code())); | 3669 actual.reg().code())); |
| 3671 } else { | 3670 } else { |
| 3672 Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate()); | 3671 Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate()); |
| 3673 } | 3672 } |
| 3674 } | 3673 } |
| 3675 | 3674 |
| 3676 // Check if next frame is an arguments adaptor frame. | 3675 // Check if next frame is an arguments adaptor frame. |
| 3677 Register caller_args_count_reg = scratch1; | 3676 Register caller_args_count_reg = scratch1; |
| 3678 Label no_arguments_adaptor, formal_parameter_count_loaded; | 3677 Label no_arguments_adaptor, formal_parameter_count_loaded; |
| 3679 __ ld(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 3678 __ Ld(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 3680 __ ld(scratch3, MemOperand(scratch2, StandardFrameConstants::kContextOffset)); | 3679 __ Ld(scratch3, MemOperand(scratch2, StandardFrameConstants::kContextOffset)); |
| 3681 __ Branch(&no_arguments_adaptor, ne, scratch3, | 3680 __ Branch(&no_arguments_adaptor, ne, scratch3, |
| 3682 Operand(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR))); | 3681 Operand(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR))); |
| 3683 | 3682 |
| 3684 // Drop current frame and load arguments count from arguments adaptor frame. | 3683 // Drop current frame and load arguments count from arguments adaptor frame. |
| 3685 __ mov(fp, scratch2); | 3684 __ mov(fp, scratch2); |
| 3686 __ ld(caller_args_count_reg, | 3685 __ Ld(caller_args_count_reg, |
| 3687 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 3686 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 3688 __ SmiUntag(caller_args_count_reg); | 3687 __ SmiUntag(caller_args_count_reg); |
| 3689 __ Branch(&formal_parameter_count_loaded); | 3688 __ Branch(&formal_parameter_count_loaded); |
| 3690 | 3689 |
| 3691 __ bind(&no_arguments_adaptor); | 3690 __ bind(&no_arguments_adaptor); |
| 3692 // Load caller's formal parameter count | 3691 // Load caller's formal parameter count |
| 3693 __ li(caller_args_count_reg, Operand(info()->literal()->parameter_count())); | 3692 __ li(caller_args_count_reg, Operand(info()->literal()->parameter_count())); |
| 3694 | 3693 |
| 3695 __ bind(&formal_parameter_count_loaded); | 3694 __ bind(&formal_parameter_count_loaded); |
| 3696 __ PrepareForTailCall(actual, caller_args_count_reg, scratch2, scratch3); | 3695 __ PrepareForTailCall(actual, caller_args_count_reg, scratch2, scratch3); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3781 | 3780 |
| 3782 if (instr->arity() == 0) { | 3781 if (instr->arity() == 0) { |
| 3783 ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode); | 3782 ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode); |
| 3784 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 3783 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 3785 } else if (instr->arity() == 1) { | 3784 } else if (instr->arity() == 1) { |
| 3786 Label done; | 3785 Label done; |
| 3787 if (IsFastPackedElementsKind(kind)) { | 3786 if (IsFastPackedElementsKind(kind)) { |
| 3788 Label packed_case; | 3787 Label packed_case; |
| 3789 // We might need a change here, | 3788 // We might need a change here, |
| 3790 // look at the first argument. | 3789 // look at the first argument. |
| 3791 __ ld(a5, MemOperand(sp, 0)); | 3790 __ Ld(a5, MemOperand(sp, 0)); |
| 3792 __ Branch(&packed_case, eq, a5, Operand(zero_reg)); | 3791 __ Branch(&packed_case, eq, a5, Operand(zero_reg)); |
| 3793 | 3792 |
| 3794 ElementsKind holey_kind = GetHoleyElementsKind(kind); | 3793 ElementsKind holey_kind = GetHoleyElementsKind(kind); |
| 3795 ArraySingleArgumentConstructorStub stub(isolate(), | 3794 ArraySingleArgumentConstructorStub stub(isolate(), |
| 3796 holey_kind, | 3795 holey_kind, |
| 3797 override_mode); | 3796 override_mode); |
| 3798 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 3797 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 3799 __ jmp(&done); | 3798 __ jmp(&done); |
| 3800 __ bind(&packed_case); | 3799 __ bind(&packed_case); |
| 3801 } | 3800 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3813 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 3812 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 3814 CallRuntime(instr->function(), instr->arity(), instr); | 3813 CallRuntime(instr->function(), instr->arity(), instr); |
| 3815 } | 3814 } |
| 3816 | 3815 |
| 3817 | 3816 |
| 3818 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { | 3817 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { |
| 3819 Register function = ToRegister(instr->function()); | 3818 Register function = ToRegister(instr->function()); |
| 3820 Register code_object = ToRegister(instr->code_object()); | 3819 Register code_object = ToRegister(instr->code_object()); |
| 3821 __ Daddu(code_object, code_object, | 3820 __ Daddu(code_object, code_object, |
| 3822 Operand(Code::kHeaderSize - kHeapObjectTag)); | 3821 Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 3823 __ sd(code_object, | 3822 __ Sd(code_object, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); |
| 3824 FieldMemOperand(function, JSFunction::kCodeEntryOffset)); | |
| 3825 } | 3823 } |
| 3826 | 3824 |
| 3827 | 3825 |
| 3828 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { | 3826 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { |
| 3829 Register result = ToRegister(instr->result()); | 3827 Register result = ToRegister(instr->result()); |
| 3830 Register base = ToRegister(instr->base_object()); | 3828 Register base = ToRegister(instr->base_object()); |
| 3831 if (instr->offset()->IsConstantOperand()) { | 3829 if (instr->offset()->IsConstantOperand()) { |
| 3832 LConstantOperand* offset = LConstantOperand::cast(instr->offset()); | 3830 LConstantOperand* offset = LConstantOperand::cast(instr->offset()); |
| 3833 __ Daddu(result, base, Operand(ToInteger32(offset))); | 3831 __ Daddu(result, base, Operand(ToInteger32(offset))); |
| 3834 } else { | 3832 } else { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 3857 __ AssertNotSmi(object); | 3855 __ AssertNotSmi(object); |
| 3858 | 3856 |
| 3859 DCHECK(!representation.IsSmi() || | 3857 DCHECK(!representation.IsSmi() || |
| 3860 !instr->value()->IsConstantOperand() || | 3858 !instr->value()->IsConstantOperand() || |
| 3861 IsSmi(LConstantOperand::cast(instr->value()))); | 3859 IsSmi(LConstantOperand::cast(instr->value()))); |
| 3862 if (!FLAG_unbox_double_fields && representation.IsDouble()) { | 3860 if (!FLAG_unbox_double_fields && representation.IsDouble()) { |
| 3863 DCHECK(access.IsInobject()); | 3861 DCHECK(access.IsInobject()); |
| 3864 DCHECK(!instr->hydrogen()->has_transition()); | 3862 DCHECK(!instr->hydrogen()->has_transition()); |
| 3865 DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); | 3863 DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); |
| 3866 DoubleRegister value = ToDoubleRegister(instr->value()); | 3864 DoubleRegister value = ToDoubleRegister(instr->value()); |
| 3867 __ sdc1(value, FieldMemOperand(object, offset)); | 3865 __ Sdc1(value, FieldMemOperand(object, offset)); |
| 3868 return; | 3866 return; |
| 3869 } | 3867 } |
| 3870 | 3868 |
| 3871 if (instr->hydrogen()->has_transition()) { | 3869 if (instr->hydrogen()->has_transition()) { |
| 3872 Handle<Map> transition = instr->hydrogen()->transition_map(); | 3870 Handle<Map> transition = instr->hydrogen()->transition_map(); |
| 3873 AddDeprecationDependency(transition); | 3871 AddDeprecationDependency(transition); |
| 3874 __ li(scratch1, Operand(transition)); | 3872 __ li(scratch1, Operand(transition)); |
| 3875 __ sd(scratch1, FieldMemOperand(object, HeapObject::kMapOffset)); | 3873 __ Sd(scratch1, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 3876 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { | 3874 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { |
| 3877 Register temp = ToRegister(instr->temp()); | 3875 Register temp = ToRegister(instr->temp()); |
| 3878 // Update the write barrier for the map field. | 3876 // Update the write barrier for the map field. |
| 3879 __ RecordWriteForMap(object, | 3877 __ RecordWriteForMap(object, |
| 3880 scratch1, | 3878 scratch1, |
| 3881 temp, | 3879 temp, |
| 3882 GetRAState(), | 3880 GetRAState(), |
| 3883 kSaveFPRegs); | 3881 kSaveFPRegs); |
| 3884 } | 3882 } |
| 3885 } | 3883 } |
| 3886 | 3884 |
| 3887 // Do the store. | 3885 // Do the store. |
| 3888 Register destination = object; | 3886 Register destination = object; |
| 3889 if (!access.IsInobject()) { | 3887 if (!access.IsInobject()) { |
| 3890 destination = scratch1; | 3888 destination = scratch1; |
| 3891 __ ld(destination, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 3889 __ Ld(destination, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 3892 } | 3890 } |
| 3893 | 3891 |
| 3894 if (representation.IsSmi() && SmiValuesAre32Bits() && | 3892 if (representation.IsSmi() && SmiValuesAre32Bits() && |
| 3895 instr->hydrogen()->value()->representation().IsInteger32()) { | 3893 instr->hydrogen()->value()->representation().IsInteger32()) { |
| 3896 DCHECK(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY); | 3894 DCHECK(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY); |
| 3897 if (FLAG_debug_code) { | 3895 if (FLAG_debug_code) { |
| 3898 __ Load(scratch2, FieldMemOperand(destination, offset), representation); | 3896 __ Load(scratch2, FieldMemOperand(destination, offset), representation); |
| 3899 __ AssertSmi(scratch2); | 3897 __ AssertSmi(scratch2); |
| 3900 } | 3898 } |
| 3901 // Store int value directly to upper half of the smi. | 3899 // Store int value directly to upper half of the smi. |
| 3902 offset = SmiWordOffset(offset); | 3900 offset = SmiWordOffset(offset); |
| 3903 representation = Representation::Integer32(); | 3901 representation = Representation::Integer32(); |
| 3904 } | 3902 } |
| 3905 MemOperand operand = FieldMemOperand(destination, offset); | 3903 MemOperand operand = FieldMemOperand(destination, offset); |
| 3906 | 3904 |
| 3907 if (FLAG_unbox_double_fields && representation.IsDouble()) { | 3905 if (FLAG_unbox_double_fields && representation.IsDouble()) { |
| 3908 DCHECK(access.IsInobject()); | 3906 DCHECK(access.IsInobject()); |
| 3909 DoubleRegister value = ToDoubleRegister(instr->value()); | 3907 DoubleRegister value = ToDoubleRegister(instr->value()); |
| 3910 __ sdc1(value, operand); | 3908 __ Sdc1(value, operand); |
| 3911 } else { | 3909 } else { |
| 3912 DCHECK(instr->value()->IsRegister()); | 3910 DCHECK(instr->value()->IsRegister()); |
| 3913 Register value = ToRegister(instr->value()); | 3911 Register value = ToRegister(instr->value()); |
| 3914 __ Store(value, operand, representation); | 3912 __ Store(value, operand, representation); |
| 3915 } | 3913 } |
| 3916 | 3914 |
| 3917 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3915 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 3918 // Update the write barrier for the object for in-object properties. | 3916 // Update the write barrier for the object for in-object properties. |
| 3919 Register value = ToRegister(instr->value()); | 3917 Register value = ToRegister(instr->value()); |
| 3920 __ RecordWriteField(destination, | 3918 __ RecordWriteField(destination, |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3991 __ dsra(address, key, -shift_size); | 3989 __ dsra(address, key, -shift_size); |
| 3992 } | 3990 } |
| 3993 } else { | 3991 } else { |
| 3994 __ dsll(address, key, shift_size); | 3992 __ dsll(address, key, shift_size); |
| 3995 } | 3993 } |
| 3996 __ Daddu(address, external_pointer, address); | 3994 __ Daddu(address, external_pointer, address); |
| 3997 } | 3995 } |
| 3998 | 3996 |
| 3999 if (elements_kind == FLOAT32_ELEMENTS) { | 3997 if (elements_kind == FLOAT32_ELEMENTS) { |
| 4000 __ cvt_s_d(double_scratch0(), value); | 3998 __ cvt_s_d(double_scratch0(), value); |
| 4001 __ swc1(double_scratch0(), MemOperand(address, base_offset)); | 3999 __ Swc1(double_scratch0(), MemOperand(address, base_offset)); |
| 4002 } else { // Storing doubles, not floats. | 4000 } else { // Storing doubles, not floats. |
| 4003 __ sdc1(value, MemOperand(address, base_offset)); | 4001 __ Sdc1(value, MemOperand(address, base_offset)); |
| 4004 } | 4002 } |
| 4005 } else { | 4003 } else { |
| 4006 Register value(ToRegister(instr->value())); | 4004 Register value(ToRegister(instr->value())); |
| 4007 MemOperand mem_operand = PrepareKeyedOperand( | 4005 MemOperand mem_operand = PrepareKeyedOperand( |
| 4008 key, external_pointer, key_is_constant, constant_key, | 4006 key, external_pointer, key_is_constant, constant_key, |
| 4009 element_size_shift, shift_size, | 4007 element_size_shift, shift_size, |
| 4010 base_offset); | 4008 base_offset); |
| 4011 switch (elements_kind) { | 4009 switch (elements_kind) { |
| 4012 case UINT8_ELEMENTS: | 4010 case UINT8_ELEMENTS: |
| 4013 case UINT8_CLAMPED_ELEMENTS: | 4011 case UINT8_CLAMPED_ELEMENTS: |
| 4014 case INT8_ELEMENTS: | 4012 case INT8_ELEMENTS: |
| 4015 __ sb(value, mem_operand); | 4013 __ Sb(value, mem_operand); |
| 4016 break; | 4014 break; |
| 4017 case INT16_ELEMENTS: | 4015 case INT16_ELEMENTS: |
| 4018 case UINT16_ELEMENTS: | 4016 case UINT16_ELEMENTS: |
| 4019 __ sh(value, mem_operand); | 4017 __ Sh(value, mem_operand); |
| 4020 break; | 4018 break; |
| 4021 case INT32_ELEMENTS: | 4019 case INT32_ELEMENTS: |
| 4022 case UINT32_ELEMENTS: | 4020 case UINT32_ELEMENTS: |
| 4023 __ sw(value, mem_operand); | 4021 __ Sw(value, mem_operand); |
| 4024 break; | 4022 break; |
| 4025 case FLOAT32_ELEMENTS: | 4023 case FLOAT32_ELEMENTS: |
| 4026 case FLOAT64_ELEMENTS: | 4024 case FLOAT64_ELEMENTS: |
| 4027 case FAST_DOUBLE_ELEMENTS: | 4025 case FAST_DOUBLE_ELEMENTS: |
| 4028 case FAST_ELEMENTS: | 4026 case FAST_ELEMENTS: |
| 4029 case FAST_SMI_ELEMENTS: | 4027 case FAST_SMI_ELEMENTS: |
| 4030 case FAST_HOLEY_DOUBLE_ELEMENTS: | 4028 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 4031 case FAST_HOLEY_ELEMENTS: | 4029 case FAST_HOLEY_ELEMENTS: |
| 4032 case FAST_HOLEY_SMI_ELEMENTS: | 4030 case FAST_HOLEY_SMI_ELEMENTS: |
| 4033 case DICTIONARY_ELEMENTS: | 4031 case DICTIONARY_ELEMENTS: |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4071 if (shift_size == 3) { | 4069 if (shift_size == 3) { |
| 4072 __ dsll(at, ToRegister(instr->key()), 3); | 4070 __ dsll(at, ToRegister(instr->key()), 3); |
| 4073 } else if (shift_size == -29) { | 4071 } else if (shift_size == -29) { |
| 4074 __ dsra(at, ToRegister(instr->key()), 29); | 4072 __ dsra(at, ToRegister(instr->key()), 29); |
| 4075 } | 4073 } |
| 4076 __ Daddu(scratch, scratch, at); | 4074 __ Daddu(scratch, scratch, at); |
| 4077 } | 4075 } |
| 4078 | 4076 |
| 4079 if (instr->NeedsCanonicalization()) { | 4077 if (instr->NeedsCanonicalization()) { |
| 4080 __ FPUCanonicalizeNaN(double_scratch, value); | 4078 __ FPUCanonicalizeNaN(double_scratch, value); |
| 4081 __ sdc1(double_scratch, MemOperand(scratch, 0)); | 4079 __ Sdc1(double_scratch, MemOperand(scratch, 0)); |
| 4082 } else { | 4080 } else { |
| 4083 __ sdc1(value, MemOperand(scratch, 0)); | 4081 __ Sdc1(value, MemOperand(scratch, 0)); |
| 4084 } | 4082 } |
| 4085 } | 4083 } |
| 4086 | 4084 |
| 4087 | 4085 |
| 4088 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { | 4086 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
| 4089 Register value = ToRegister(instr->value()); | 4087 Register value = ToRegister(instr->value()); |
| 4090 Register elements = ToRegister(instr->elements()); | 4088 Register elements = ToRegister(instr->elements()); |
| 4091 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) | 4089 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) |
| 4092 : no_reg; | 4090 : no_reg; |
| 4093 Register scratch = scratch0(); | 4091 Register scratch = scratch0(); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4204 __ Branch(deferred->entry(), ge, ToRegister(key), | 4202 __ Branch(deferred->entry(), ge, ToRegister(key), |
| 4205 Operand(constant_capacity)); | 4203 Operand(constant_capacity)); |
| 4206 } else { | 4204 } else { |
| 4207 __ Branch(deferred->entry(), ge, ToRegister(key), | 4205 __ Branch(deferred->entry(), ge, ToRegister(key), |
| 4208 Operand(ToRegister(current_capacity))); | 4206 Operand(ToRegister(current_capacity))); |
| 4209 } | 4207 } |
| 4210 | 4208 |
| 4211 if (instr->elements()->IsRegister()) { | 4209 if (instr->elements()->IsRegister()) { |
| 4212 __ mov(result, ToRegister(instr->elements())); | 4210 __ mov(result, ToRegister(instr->elements())); |
| 4213 } else { | 4211 } else { |
| 4214 __ ld(result, ToMemOperand(instr->elements())); | 4212 __ Ld(result, ToMemOperand(instr->elements())); |
| 4215 } | 4213 } |
| 4216 | 4214 |
| 4217 __ bind(deferred->exit()); | 4215 __ bind(deferred->exit()); |
| 4218 } | 4216 } |
| 4219 | 4217 |
| 4220 | 4218 |
| 4221 void LCodeGen::DoDeferredMaybeGrowElements(LMaybeGrowElements* instr) { | 4219 void LCodeGen::DoDeferredMaybeGrowElements(LMaybeGrowElements* instr) { |
| 4222 // TODO(3095996): Get rid of this. For now, we need to make the | 4220 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4223 // result register contain a valid pointer because it is already | 4221 // result register contain a valid pointer because it is already |
| 4224 // contained in the register pointer map. | 4222 // contained in the register pointer map. |
| 4225 Register result = v0; | 4223 Register result = v0; |
| 4226 __ mov(result, zero_reg); | 4224 __ mov(result, zero_reg); |
| 4227 | 4225 |
| 4228 // We have to call a stub. | 4226 // We have to call a stub. |
| 4229 { | 4227 { |
| 4230 PushSafepointRegistersScope scope(this); | 4228 PushSafepointRegistersScope scope(this); |
| 4231 if (instr->object()->IsRegister()) { | 4229 if (instr->object()->IsRegister()) { |
| 4232 __ mov(result, ToRegister(instr->object())); | 4230 __ mov(result, ToRegister(instr->object())); |
| 4233 } else { | 4231 } else { |
| 4234 __ ld(result, ToMemOperand(instr->object())); | 4232 __ Ld(result, ToMemOperand(instr->object())); |
| 4235 } | 4233 } |
| 4236 | 4234 |
| 4237 LOperand* key = instr->key(); | 4235 LOperand* key = instr->key(); |
| 4238 if (key->IsConstantOperand()) { | 4236 if (key->IsConstantOperand()) { |
| 4239 __ li(a3, Operand(ToSmi(LConstantOperand::cast(key)))); | 4237 __ li(a3, Operand(ToSmi(LConstantOperand::cast(key)))); |
| 4240 } else { | 4238 } else { |
| 4241 __ mov(a3, ToRegister(key)); | 4239 __ mov(a3, ToRegister(key)); |
| 4242 __ SmiTag(a3); | 4240 __ SmiTag(a3); |
| 4243 } | 4241 } |
| 4244 | 4242 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4259 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 4257 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
| 4260 Register object_reg = ToRegister(instr->object()); | 4258 Register object_reg = ToRegister(instr->object()); |
| 4261 Register scratch = scratch0(); | 4259 Register scratch = scratch0(); |
| 4262 | 4260 |
| 4263 Handle<Map> from_map = instr->original_map(); | 4261 Handle<Map> from_map = instr->original_map(); |
| 4264 Handle<Map> to_map = instr->transitioned_map(); | 4262 Handle<Map> to_map = instr->transitioned_map(); |
| 4265 ElementsKind from_kind = instr->from_kind(); | 4263 ElementsKind from_kind = instr->from_kind(); |
| 4266 ElementsKind to_kind = instr->to_kind(); | 4264 ElementsKind to_kind = instr->to_kind(); |
| 4267 | 4265 |
| 4268 Label not_applicable; | 4266 Label not_applicable; |
| 4269 __ ld(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 4267 __ Ld(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
| 4270 __ Branch(¬_applicable, ne, scratch, Operand(from_map)); | 4268 __ Branch(¬_applicable, ne, scratch, Operand(from_map)); |
| 4271 | 4269 |
| 4272 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { | 4270 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
| 4273 Register new_map_reg = ToRegister(instr->new_map_temp()); | 4271 Register new_map_reg = ToRegister(instr->new_map_temp()); |
| 4274 __ li(new_map_reg, Operand(to_map)); | 4272 __ li(new_map_reg, Operand(to_map)); |
| 4275 __ sd(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 4273 __ Sd(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
| 4276 // Write barrier. | 4274 // Write barrier. |
| 4277 __ RecordWriteForMap(object_reg, | 4275 __ RecordWriteForMap(object_reg, |
| 4278 new_map_reg, | 4276 new_map_reg, |
| 4279 scratch, | 4277 scratch, |
| 4280 GetRAState(), | 4278 GetRAState(), |
| 4281 kDontSaveFPRegs); | 4279 kDontSaveFPRegs); |
| 4282 } else { | 4280 } else { |
| 4283 DCHECK(object_reg.is(a0)); | 4281 DCHECK(object_reg.is(a0)); |
| 4284 DCHECK(ToRegister(instr->context()).is(cp)); | 4282 DCHECK(ToRegister(instr->context()).is(cp)); |
| 4285 PushSafepointRegistersScope scope(this); | 4283 PushSafepointRegistersScope scope(this); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4388 DCHECK(instr->hydrogen()->value()->representation().IsInteger32()); | 4386 DCHECK(instr->hydrogen()->value()->representation().IsInteger32()); |
| 4389 Register char_code = ToRegister(instr->char_code()); | 4387 Register char_code = ToRegister(instr->char_code()); |
| 4390 Register result = ToRegister(instr->result()); | 4388 Register result = ToRegister(instr->result()); |
| 4391 Register scratch = scratch0(); | 4389 Register scratch = scratch0(); |
| 4392 DCHECK(!char_code.is(result)); | 4390 DCHECK(!char_code.is(result)); |
| 4393 | 4391 |
| 4394 __ Branch(deferred->entry(), hi, | 4392 __ Branch(deferred->entry(), hi, |
| 4395 char_code, Operand(String::kMaxOneByteCharCode)); | 4393 char_code, Operand(String::kMaxOneByteCharCode)); |
| 4396 __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex); | 4394 __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex); |
| 4397 __ Dlsa(result, result, char_code, kPointerSizeLog2); | 4395 __ Dlsa(result, result, char_code, kPointerSizeLog2); |
| 4398 __ ld(result, FieldMemOperand(result, FixedArray::kHeaderSize)); | 4396 __ Ld(result, FieldMemOperand(result, FixedArray::kHeaderSize)); |
| 4399 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); | 4397 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
| 4400 __ Branch(deferred->entry(), eq, result, Operand(scratch)); | 4398 __ Branch(deferred->entry(), eq, result, Operand(scratch)); |
| 4401 __ bind(deferred->exit()); | 4399 __ bind(deferred->exit()); |
| 4402 } | 4400 } |
| 4403 | 4401 |
| 4404 | 4402 |
| 4405 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { | 4403 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { |
| 4406 Register char_code = ToRegister(instr->char_code()); | 4404 Register char_code = ToRegister(instr->char_code()); |
| 4407 Register result = ToRegister(instr->result()); | 4405 Register result = ToRegister(instr->result()); |
| 4408 | 4406 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4421 | 4419 |
| 4422 | 4420 |
| 4423 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4421 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 4424 LOperand* input = instr->value(); | 4422 LOperand* input = instr->value(); |
| 4425 DCHECK(input->IsRegister() || input->IsStackSlot()); | 4423 DCHECK(input->IsRegister() || input->IsStackSlot()); |
| 4426 LOperand* output = instr->result(); | 4424 LOperand* output = instr->result(); |
| 4427 DCHECK(output->IsDoubleRegister()); | 4425 DCHECK(output->IsDoubleRegister()); |
| 4428 FPURegister single_scratch = double_scratch0().low(); | 4426 FPURegister single_scratch = double_scratch0().low(); |
| 4429 if (input->IsStackSlot()) { | 4427 if (input->IsStackSlot()) { |
| 4430 Register scratch = scratch0(); | 4428 Register scratch = scratch0(); |
| 4431 __ ld(scratch, ToMemOperand(input)); | 4429 __ Ld(scratch, ToMemOperand(input)); |
| 4432 __ mtc1(scratch, single_scratch); | 4430 __ mtc1(scratch, single_scratch); |
| 4433 } else { | 4431 } else { |
| 4434 __ mtc1(ToRegister(input), single_scratch); | 4432 __ mtc1(ToRegister(input), single_scratch); |
| 4435 } | 4433 } |
| 4436 __ cvt_d_w(ToDoubleRegister(output), single_scratch); | 4434 __ cvt_d_w(ToDoubleRegister(output), single_scratch); |
| 4437 } | 4435 } |
| 4438 | 4436 |
| 4439 | 4437 |
| 4440 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { | 4438 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
| 4441 LOperand* input = instr->value(); | 4439 LOperand* input = instr->value(); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4524 } | 4522 } |
| 4525 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 4523 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 4526 RecordSafepointWithRegisters( | 4524 RecordSafepointWithRegisters( |
| 4527 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4525 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4528 __ StoreToSafepointRegisterSlot(v0, dst); | 4526 __ StoreToSafepointRegisterSlot(v0, dst); |
| 4529 } | 4527 } |
| 4530 | 4528 |
| 4531 // Done. Put the value in dbl_scratch into the value of the allocated heap | 4529 // Done. Put the value in dbl_scratch into the value of the allocated heap |
| 4532 // number. | 4530 // number. |
| 4533 __ bind(&done); | 4531 __ bind(&done); |
| 4534 __ sdc1(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset)); | 4532 __ Sdc1(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset)); |
| 4535 } | 4533 } |
| 4536 | 4534 |
| 4537 | 4535 |
| 4538 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 4536 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
| 4539 class DeferredNumberTagD final : public LDeferredCode { | 4537 class DeferredNumberTagD final : public LDeferredCode { |
| 4540 public: | 4538 public: |
| 4541 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4539 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 4542 : LDeferredCode(codegen), instr_(instr) { } | 4540 : LDeferredCode(codegen), instr_(instr) { } |
| 4543 void Generate() override { codegen()->DoDeferredNumberTagD(instr_); } | 4541 void Generate() override { codegen()->DoDeferredNumberTagD(instr_); } |
| 4544 LInstruction* instr() override { return instr_; } | 4542 LInstruction* instr() override { return instr_; } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4555 | 4553 |
| 4556 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4554 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
| 4557 if (FLAG_inline_new) { | 4555 if (FLAG_inline_new) { |
| 4558 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 4556 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
| 4559 // We want the untagged address first for performance | 4557 // We want the untagged address first for performance |
| 4560 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); | 4558 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); |
| 4561 } else { | 4559 } else { |
| 4562 __ Branch(deferred->entry()); | 4560 __ Branch(deferred->entry()); |
| 4563 } | 4561 } |
| 4564 __ bind(deferred->exit()); | 4562 __ bind(deferred->exit()); |
| 4565 __ sdc1(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 4563 __ Sdc1(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
| 4566 } | 4564 } |
| 4567 | 4565 |
| 4568 | 4566 |
| 4569 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4567 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 4570 // TODO(3095996): Get rid of this. For now, we need to make the | 4568 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4571 // result register contain a valid pointer because it is already | 4569 // result register contain a valid pointer because it is already |
| 4572 // contained in the register pointer map. | 4570 // contained in the register pointer map. |
| 4573 Register reg = ToRegister(instr->result()); | 4571 Register reg = ToRegister(instr->result()); |
| 4574 __ mov(reg, zero_reg); | 4572 __ mov(reg, zero_reg); |
| 4575 | 4573 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4626 NumberUntagDMode mode) { | 4624 NumberUntagDMode mode) { |
| 4627 bool can_convert_undefined_to_nan = instr->truncating(); | 4625 bool can_convert_undefined_to_nan = instr->truncating(); |
| 4628 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); | 4626 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); |
| 4629 | 4627 |
| 4630 Register scratch = scratch0(); | 4628 Register scratch = scratch0(); |
| 4631 Label convert, load_smi, done; | 4629 Label convert, load_smi, done; |
| 4632 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { | 4630 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| 4633 // Smi check. | 4631 // Smi check. |
| 4634 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); | 4632 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); |
| 4635 // Heap number map check. | 4633 // Heap number map check. |
| 4636 __ ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4634 __ Ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4637 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 4635 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 4638 if (can_convert_undefined_to_nan) { | 4636 if (can_convert_undefined_to_nan) { |
| 4639 __ Branch(&convert, ne, scratch, Operand(at)); | 4637 __ Branch(&convert, ne, scratch, Operand(at)); |
| 4640 } else { | 4638 } else { |
| 4641 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch, | 4639 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch, |
| 4642 Operand(at)); | 4640 Operand(at)); |
| 4643 } | 4641 } |
| 4644 // Load heap number. | 4642 // Load heap number. |
| 4645 __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 4643 __ Ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
| 4646 if (deoptimize_on_minus_zero) { | 4644 if (deoptimize_on_minus_zero) { |
| 4647 __ mfc1(at, result_reg); | 4645 __ mfc1(at, result_reg); |
| 4648 __ Branch(&done, ne, at, Operand(zero_reg)); | 4646 __ Branch(&done, ne, at, Operand(zero_reg)); |
| 4649 __ mfhc1(scratch, result_reg); // Get exponent/sign bits. | 4647 __ mfhc1(scratch, result_reg); // Get exponent/sign bits. |
| 4650 DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, scratch, | 4648 DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, scratch, |
| 4651 Operand(HeapNumber::kSignMask)); | 4649 Operand(HeapNumber::kSignMask)); |
| 4652 } | 4650 } |
| 4653 __ Branch(&done); | 4651 __ Branch(&done); |
| 4654 if (can_convert_undefined_to_nan) { | 4652 if (can_convert_undefined_to_nan) { |
| 4655 __ bind(&convert); | 4653 __ bind(&convert); |
| 4656 // Convert undefined (and hole) to NaN. | 4654 // Convert undefined (and hole) to NaN. |
| 4657 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 4655 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 4658 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined, | 4656 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined, |
| 4659 input_reg, Operand(at)); | 4657 input_reg, Operand(at)); |
| 4660 __ LoadRoot(scratch, Heap::kNanValueRootIndex); | 4658 __ LoadRoot(scratch, Heap::kNanValueRootIndex); |
| 4661 __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset)); | 4659 __ Ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset)); |
| 4662 __ Branch(&done); | 4660 __ Branch(&done); |
| 4663 } | 4661 } |
| 4664 } else { | 4662 } else { |
| 4665 __ SmiUntag(scratch, input_reg); | 4663 __ SmiUntag(scratch, input_reg); |
| 4666 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); | 4664 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); |
| 4667 } | 4665 } |
| 4668 // Smi to double register conversion | 4666 // Smi to double register conversion |
| 4669 __ bind(&load_smi); | 4667 __ bind(&load_smi); |
| 4670 // scratch: untagged value of input_reg | 4668 // scratch: untagged value of input_reg |
| 4671 __ mtc1(scratch, result_reg); | 4669 __ mtc1(scratch, result_reg); |
| 4672 __ cvt_d_w(result_reg, result_reg); | 4670 __ cvt_d_w(result_reg, result_reg); |
| 4673 __ bind(&done); | 4671 __ bind(&done); |
| 4674 } | 4672 } |
| 4675 | 4673 |
| 4676 | 4674 |
| 4677 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 4675 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
| 4678 Register input_reg = ToRegister(instr->value()); | 4676 Register input_reg = ToRegister(instr->value()); |
| 4679 Register scratch1 = scratch0(); | 4677 Register scratch1 = scratch0(); |
| 4680 Register scratch2 = ToRegister(instr->temp()); | 4678 Register scratch2 = ToRegister(instr->temp()); |
| 4681 DoubleRegister double_scratch = double_scratch0(); | 4679 DoubleRegister double_scratch = double_scratch0(); |
| 4682 DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp2()); | 4680 DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp2()); |
| 4683 | 4681 |
| 4684 DCHECK(!scratch1.is(input_reg) && !scratch1.is(scratch2)); | 4682 DCHECK(!scratch1.is(input_reg) && !scratch1.is(scratch2)); |
| 4685 DCHECK(!scratch2.is(input_reg) && !scratch2.is(scratch1)); | 4683 DCHECK(!scratch2.is(input_reg) && !scratch2.is(scratch1)); |
| 4686 | 4684 |
| 4687 Label done; | 4685 Label done; |
| 4688 | 4686 |
| 4689 // The input is a tagged HeapObject. | 4687 // The input is a tagged HeapObject. |
| 4690 // Heap number map check. | 4688 // Heap number map check. |
| 4691 __ ld(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4689 __ Ld(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4692 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 4690 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 4693 // This 'at' value and scratch1 map value are used for tests in both clauses | 4691 // This 'at' value and scratch1 map value are used for tests in both clauses |
| 4694 // of the if. | 4692 // of the if. |
| 4695 | 4693 |
| 4696 if (instr->truncating()) { | 4694 if (instr->truncating()) { |
| 4697 Label truncate; | 4695 Label truncate; |
| 4698 __ Branch(USE_DELAY_SLOT, &truncate, eq, scratch1, Operand(at)); | 4696 __ Branch(USE_DELAY_SLOT, &truncate, eq, scratch1, Operand(at)); |
| 4699 __ mov(scratch2, input_reg); // In delay slot. | 4697 __ mov(scratch2, input_reg); // In delay slot. |
| 4700 __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | 4698 __ Lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
| 4701 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotANumberOrOddball, scratch1, | 4699 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotANumberOrOddball, scratch1, |
| 4702 Operand(ODDBALL_TYPE)); | 4700 Operand(ODDBALL_TYPE)); |
| 4703 __ bind(&truncate); | 4701 __ bind(&truncate); |
| 4704 __ TruncateHeapNumberToI(input_reg, scratch2); | 4702 __ TruncateHeapNumberToI(input_reg, scratch2); |
| 4705 } else { | 4703 } else { |
| 4706 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch1, | 4704 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch1, |
| 4707 Operand(at)); | 4705 Operand(at)); |
| 4708 | 4706 |
| 4709 // Load the double value. | 4707 // Load the double value. |
| 4710 __ ldc1(double_scratch, | 4708 __ Ldc1(double_scratch, |
| 4711 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 4709 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
| 4712 | 4710 |
| 4713 Register except_flag = scratch2; | 4711 Register except_flag = scratch2; |
| 4714 __ EmitFPUTruncate(kRoundToZero, | 4712 __ EmitFPUTruncate(kRoundToZero, |
| 4715 input_reg, | 4713 input_reg, |
| 4716 double_scratch, | 4714 double_scratch, |
| 4717 scratch1, | 4715 scratch1, |
| 4718 double_scratch2, | 4716 double_scratch2, |
| 4719 except_flag, | 4717 except_flag, |
| 4720 kCheckForInexactConversion); | 4718 kCheckForInexactConversion); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4870 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, at, Operand(zero_reg)); | 4868 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, at, Operand(zero_reg)); |
| 4871 } | 4869 } |
| 4872 } | 4870 } |
| 4873 | 4871 |
| 4874 | 4872 |
| 4875 void LCodeGen::DoCheckArrayBufferNotNeutered( | 4873 void LCodeGen::DoCheckArrayBufferNotNeutered( |
| 4876 LCheckArrayBufferNotNeutered* instr) { | 4874 LCheckArrayBufferNotNeutered* instr) { |
| 4877 Register view = ToRegister(instr->view()); | 4875 Register view = ToRegister(instr->view()); |
| 4878 Register scratch = scratch0(); | 4876 Register scratch = scratch0(); |
| 4879 | 4877 |
| 4880 __ ld(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset)); | 4878 __ Ld(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset)); |
| 4881 __ lw(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset)); | 4879 __ Lw(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset)); |
| 4882 __ And(at, scratch, 1 << JSArrayBuffer::WasNeutered::kShift); | 4880 __ And(at, scratch, 1 << JSArrayBuffer::WasNeutered::kShift); |
| 4883 DeoptimizeIf(ne, instr, DeoptimizeReason::kOutOfBounds, at, | 4881 DeoptimizeIf(ne, instr, DeoptimizeReason::kOutOfBounds, at, |
| 4884 Operand(zero_reg)); | 4882 Operand(zero_reg)); |
| 4885 } | 4883 } |
| 4886 | 4884 |
| 4887 | 4885 |
| 4888 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 4886 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
| 4889 Register input = ToRegister(instr->value()); | 4887 Register input = ToRegister(instr->value()); |
| 4890 Register scratch = scratch0(); | 4888 Register scratch = scratch0(); |
| 4891 | 4889 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4929 | 4927 |
| 4930 | 4928 |
| 4931 void LCodeGen::DoCheckValue(LCheckValue* instr) { | 4929 void LCodeGen::DoCheckValue(LCheckValue* instr) { |
| 4932 Register reg = ToRegister(instr->value()); | 4930 Register reg = ToRegister(instr->value()); |
| 4933 Handle<HeapObject> object = instr->hydrogen()->object().handle(); | 4931 Handle<HeapObject> object = instr->hydrogen()->object().handle(); |
| 4934 AllowDeferredHandleDereference smi_check; | 4932 AllowDeferredHandleDereference smi_check; |
| 4935 if (isolate()->heap()->InNewSpace(*object)) { | 4933 if (isolate()->heap()->InNewSpace(*object)) { |
| 4936 Register reg = ToRegister(instr->value()); | 4934 Register reg = ToRegister(instr->value()); |
| 4937 Handle<Cell> cell = isolate()->factory()->NewCell(object); | 4935 Handle<Cell> cell = isolate()->factory()->NewCell(object); |
| 4938 __ li(at, Operand(cell)); | 4936 __ li(at, Operand(cell)); |
| 4939 __ ld(at, FieldMemOperand(at, Cell::kValueOffset)); | 4937 __ Ld(at, FieldMemOperand(at, Cell::kValueOffset)); |
| 4940 DeoptimizeIf(ne, instr, DeoptimizeReason::kValueMismatch, reg, Operand(at)); | 4938 DeoptimizeIf(ne, instr, DeoptimizeReason::kValueMismatch, reg, Operand(at)); |
| 4941 } else { | 4939 } else { |
| 4942 DeoptimizeIf(ne, instr, DeoptimizeReason::kValueMismatch, reg, | 4940 DeoptimizeIf(ne, instr, DeoptimizeReason::kValueMismatch, reg, |
| 4943 Operand(object)); | 4941 Operand(object)); |
| 4944 } | 4942 } |
| 4945 } | 4943 } |
| 4946 | 4944 |
| 4947 | 4945 |
| 4948 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 4946 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
| 4949 Label deopt, done; | 4947 Label deopt, done; |
| 4950 // If the map is not deprecated the migration attempt does not make sense. | 4948 // If the map is not deprecated the migration attempt does not make sense. |
| 4951 __ ld(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); | 4949 __ Ld(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); |
| 4952 __ lwu(scratch0(), FieldMemOperand(scratch0(), Map::kBitField3Offset)); | 4950 __ Lwu(scratch0(), FieldMemOperand(scratch0(), Map::kBitField3Offset)); |
| 4953 __ And(at, scratch0(), Operand(Map::Deprecated::kMask)); | 4951 __ And(at, scratch0(), Operand(Map::Deprecated::kMask)); |
| 4954 __ Branch(&deopt, eq, at, Operand(zero_reg)); | 4952 __ Branch(&deopt, eq, at, Operand(zero_reg)); |
| 4955 | 4953 |
| 4956 { | 4954 { |
| 4957 PushSafepointRegistersScope scope(this); | 4955 PushSafepointRegistersScope scope(this); |
| 4958 __ push(object); | 4956 __ push(object); |
| 4959 __ mov(cp, zero_reg); | 4957 __ mov(cp, zero_reg); |
| 4960 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); | 4958 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); |
| 4961 RecordSafepointWithRegisters( | 4959 RecordSafepointWithRegisters( |
| 4962 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); | 4960 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4999 for (int i = 0; i < maps->size(); ++i) { | 4997 for (int i = 0; i < maps->size(); ++i) { |
| 5000 AddStabilityDependency(maps->at(i).handle()); | 4998 AddStabilityDependency(maps->at(i).handle()); |
| 5001 } | 4999 } |
| 5002 return; | 5000 return; |
| 5003 } | 5001 } |
| 5004 | 5002 |
| 5005 Register map_reg = scratch0(); | 5003 Register map_reg = scratch0(); |
| 5006 LOperand* input = instr->value(); | 5004 LOperand* input = instr->value(); |
| 5007 DCHECK(input->IsRegister()); | 5005 DCHECK(input->IsRegister()); |
| 5008 Register reg = ToRegister(input); | 5006 Register reg = ToRegister(input); |
| 5009 __ ld(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); | 5007 __ Ld(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 5010 | 5008 |
| 5011 DeferredCheckMaps* deferred = NULL; | 5009 DeferredCheckMaps* deferred = NULL; |
| 5012 if (instr->hydrogen()->HasMigrationTarget()) { | 5010 if (instr->hydrogen()->HasMigrationTarget()) { |
| 5013 deferred = new(zone()) DeferredCheckMaps(this, instr, reg); | 5011 deferred = new(zone()) DeferredCheckMaps(this, instr, reg); |
| 5014 __ bind(deferred->check_maps()); | 5012 __ bind(deferred->check_maps()); |
| 5015 } | 5013 } |
| 5016 | 5014 |
| 5017 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); | 5015 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); |
| 5018 Label success; | 5016 Label success; |
| 5019 for (int i = 0; i < maps->size() - 1; i++) { | 5017 for (int i = 0; i < maps->size() - 1; i++) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5051 Register scratch = scratch0(); | 5049 Register scratch = scratch0(); |
| 5052 Register input_reg = ToRegister(instr->unclamped()); | 5050 Register input_reg = ToRegister(instr->unclamped()); |
| 5053 Register result_reg = ToRegister(instr->result()); | 5051 Register result_reg = ToRegister(instr->result()); |
| 5054 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); | 5052 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); |
| 5055 Label is_smi, done, heap_number; | 5053 Label is_smi, done, heap_number; |
| 5056 | 5054 |
| 5057 // Both smi and heap number cases are handled. | 5055 // Both smi and heap number cases are handled. |
| 5058 __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi); | 5056 __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi); |
| 5059 | 5057 |
| 5060 // Check for heap number | 5058 // Check for heap number |
| 5061 __ ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 5059 __ Ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 5062 __ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map())); | 5060 __ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map())); |
| 5063 | 5061 |
| 5064 // Check for undefined. Undefined is converted to zero for clamping | 5062 // Check for undefined. Undefined is converted to zero for clamping |
| 5065 // conversions. | 5063 // conversions. |
| 5066 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined, input_reg, | 5064 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined, input_reg, |
| 5067 Operand(factory()->undefined_value())); | 5065 Operand(factory()->undefined_value())); |
| 5068 __ mov(result_reg, zero_reg); | 5066 __ mov(result_reg, zero_reg); |
| 5069 __ jmp(&done); | 5067 __ jmp(&done); |
| 5070 | 5068 |
| 5071 // Heap number | 5069 // Heap number |
| 5072 __ bind(&heap_number); | 5070 __ bind(&heap_number); |
| 5073 __ ldc1(double_scratch0(), FieldMemOperand(input_reg, | 5071 __ Ldc1(double_scratch0(), |
| 5074 HeapNumber::kValueOffset)); | 5072 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
| 5075 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); | 5073 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); |
| 5076 __ jmp(&done); | 5074 __ jmp(&done); |
| 5077 | 5075 |
| 5078 __ bind(&is_smi); | 5076 __ bind(&is_smi); |
| 5079 __ ClampUint8(result_reg, scratch); | 5077 __ ClampUint8(result_reg, scratch); |
| 5080 | 5078 |
| 5081 __ bind(&done); | 5079 __ bind(&done); |
| 5082 } | 5080 } |
| 5083 | 5081 |
| 5084 | 5082 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5133 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5131 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
| 5134 __ li(scratch, Operand(size - kHeapObjectTag)); | 5132 __ li(scratch, Operand(size - kHeapObjectTag)); |
| 5135 } else { | 5133 } else { |
| 5136 __ Dsubu(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag)); | 5134 __ Dsubu(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag)); |
| 5137 } | 5135 } |
| 5138 __ li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); | 5136 __ li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); |
| 5139 Label loop; | 5137 Label loop; |
| 5140 __ bind(&loop); | 5138 __ bind(&loop); |
| 5141 __ Dsubu(scratch, scratch, Operand(kPointerSize)); | 5139 __ Dsubu(scratch, scratch, Operand(kPointerSize)); |
| 5142 __ Daddu(at, result, Operand(scratch)); | 5140 __ Daddu(at, result, Operand(scratch)); |
| 5143 __ sd(scratch2, MemOperand(at)); | 5141 __ Sd(scratch2, MemOperand(at)); |
| 5144 __ Branch(&loop, ge, scratch, Operand(zero_reg)); | 5142 __ Branch(&loop, ge, scratch, Operand(zero_reg)); |
| 5145 } | 5143 } |
| 5146 } | 5144 } |
| 5147 | 5145 |
| 5148 | 5146 |
| 5149 void LCodeGen::DoDeferredAllocate(LAllocate* instr) { | 5147 void LCodeGen::DoDeferredAllocate(LAllocate* instr) { |
| 5150 Register result = ToRegister(instr->result()); | 5148 Register result = ToRegister(instr->result()); |
| 5151 | 5149 |
| 5152 // TODO(3095996): Get rid of this. For now, we need to make the | 5150 // TODO(3095996): Get rid of this. For now, we need to make the |
| 5153 // result register contain a valid pointer because it is already | 5151 // result register contain a valid pointer because it is already |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5194 allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE); | 5192 allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE); |
| 5195 } | 5193 } |
| 5196 // If the allocation folding dominator allocate triggered a GC, allocation | 5194 // If the allocation folding dominator allocate triggered a GC, allocation |
| 5197 // happend in the runtime. We have to reset the top pointer to virtually | 5195 // happend in the runtime. We have to reset the top pointer to virtually |
| 5198 // undo the allocation. | 5196 // undo the allocation. |
| 5199 ExternalReference allocation_top = | 5197 ExternalReference allocation_top = |
| 5200 AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags); | 5198 AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags); |
| 5201 Register top_address = scratch0(); | 5199 Register top_address = scratch0(); |
| 5202 __ Dsubu(v0, v0, Operand(kHeapObjectTag)); | 5200 __ Dsubu(v0, v0, Operand(kHeapObjectTag)); |
| 5203 __ li(top_address, Operand(allocation_top)); | 5201 __ li(top_address, Operand(allocation_top)); |
| 5204 __ sd(v0, MemOperand(top_address)); | 5202 __ Sd(v0, MemOperand(top_address)); |
| 5205 __ Daddu(v0, v0, Operand(kHeapObjectTag)); | 5203 __ Daddu(v0, v0, Operand(kHeapObjectTag)); |
| 5206 } | 5204 } |
| 5207 } | 5205 } |
| 5208 | 5206 |
| 5209 void LCodeGen::DoFastAllocate(LFastAllocate* instr) { | 5207 void LCodeGen::DoFastAllocate(LFastAllocate* instr) { |
| 5210 DCHECK(instr->hydrogen()->IsAllocationFolded()); | 5208 DCHECK(instr->hydrogen()->IsAllocationFolded()); |
| 5211 DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator()); | 5209 DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator()); |
| 5212 Register result = ToRegister(instr->result()); | 5210 Register result = ToRegister(instr->result()); |
| 5213 Register scratch1 = ToRegister(instr->temp1()); | 5211 Register scratch1 = ToRegister(instr->temp1()); |
| 5214 Register scratch2 = ToRegister(instr->temp2()); | 5212 Register scratch2 = ToRegister(instr->temp2()); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5276 Register* cmp1, | 5274 Register* cmp1, |
| 5277 Operand* cmp2) { | 5275 Operand* cmp2) { |
| 5278 // This function utilizes the delay slot heavily. This is used to load | 5276 // This function utilizes the delay slot heavily. This is used to load |
| 5279 // values that are always usable without depending on the type of the input | 5277 // values that are always usable without depending on the type of the input |
| 5280 // register. | 5278 // register. |
| 5281 Condition final_branch_condition = kNoCondition; | 5279 Condition final_branch_condition = kNoCondition; |
| 5282 Register scratch = scratch0(); | 5280 Register scratch = scratch0(); |
| 5283 Factory* factory = isolate()->factory(); | 5281 Factory* factory = isolate()->factory(); |
| 5284 if (String::Equals(type_name, factory->number_string())) { | 5282 if (String::Equals(type_name, factory->number_string())) { |
| 5285 __ JumpIfSmi(input, true_label); | 5283 __ JumpIfSmi(input, true_label); |
| 5286 __ ld(input, FieldMemOperand(input, HeapObject::kMapOffset)); | 5284 __ Ld(input, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 5287 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 5285 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 5288 *cmp1 = input; | 5286 *cmp1 = input; |
| 5289 *cmp2 = Operand(at); | 5287 *cmp2 = Operand(at); |
| 5290 final_branch_condition = eq; | 5288 final_branch_condition = eq; |
| 5291 | 5289 |
| 5292 } else if (String::Equals(type_name, factory->string_string())) { | 5290 } else if (String::Equals(type_name, factory->string_string())) { |
| 5293 __ JumpIfSmi(input, false_label); | 5291 __ JumpIfSmi(input, false_label); |
| 5294 __ GetObjectType(input, input, scratch); | 5292 __ GetObjectType(input, input, scratch); |
| 5295 *cmp1 = scratch; | 5293 *cmp1 = scratch; |
| 5296 *cmp2 = Operand(FIRST_NONSTRING_TYPE); | 5294 *cmp2 = Operand(FIRST_NONSTRING_TYPE); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5311 *cmp2 = Operand(input); | 5309 *cmp2 = Operand(input); |
| 5312 final_branch_condition = eq; | 5310 final_branch_condition = eq; |
| 5313 | 5311 |
| 5314 } else if (String::Equals(type_name, factory->undefined_string())) { | 5312 } else if (String::Equals(type_name, factory->undefined_string())) { |
| 5315 __ LoadRoot(at, Heap::kNullValueRootIndex); | 5313 __ LoadRoot(at, Heap::kNullValueRootIndex); |
| 5316 __ Branch(USE_DELAY_SLOT, false_label, eq, at, Operand(input)); | 5314 __ Branch(USE_DELAY_SLOT, false_label, eq, at, Operand(input)); |
| 5317 // The first instruction of JumpIfSmi is an And - it is safe in the delay | 5315 // The first instruction of JumpIfSmi is an And - it is safe in the delay |
| 5318 // slot. | 5316 // slot. |
| 5319 __ JumpIfSmi(input, false_label); | 5317 __ JumpIfSmi(input, false_label); |
| 5320 // Check for undetectable objects => true. | 5318 // Check for undetectable objects => true. |
| 5321 __ ld(input, FieldMemOperand(input, HeapObject::kMapOffset)); | 5319 __ Ld(input, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 5322 __ lbu(at, FieldMemOperand(input, Map::kBitFieldOffset)); | 5320 __ Lbu(at, FieldMemOperand(input, Map::kBitFieldOffset)); |
| 5323 __ And(at, at, 1 << Map::kIsUndetectable); | 5321 __ And(at, at, 1 << Map::kIsUndetectable); |
| 5324 *cmp1 = at; | 5322 *cmp1 = at; |
| 5325 *cmp2 = Operand(zero_reg); | 5323 *cmp2 = Operand(zero_reg); |
| 5326 final_branch_condition = ne; | 5324 final_branch_condition = ne; |
| 5327 | 5325 |
| 5328 } else if (String::Equals(type_name, factory->function_string())) { | 5326 } else if (String::Equals(type_name, factory->function_string())) { |
| 5329 __ JumpIfSmi(input, false_label); | 5327 __ JumpIfSmi(input, false_label); |
| 5330 __ ld(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 5328 __ Ld(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 5331 __ lbu(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); | 5329 __ Lbu(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); |
| 5332 __ And(scratch, scratch, | 5330 __ And(scratch, scratch, |
| 5333 Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable))); | 5331 Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable))); |
| 5334 *cmp1 = scratch; | 5332 *cmp1 = scratch; |
| 5335 *cmp2 = Operand(1 << Map::kIsCallable); | 5333 *cmp2 = Operand(1 << Map::kIsCallable); |
| 5336 final_branch_condition = eq; | 5334 final_branch_condition = eq; |
| 5337 | 5335 |
| 5338 } else if (String::Equals(type_name, factory->object_string())) { | 5336 } else if (String::Equals(type_name, factory->object_string())) { |
| 5339 __ JumpIfSmi(input, false_label); | 5337 __ JumpIfSmi(input, false_label); |
| 5340 __ LoadRoot(at, Heap::kNullValueRootIndex); | 5338 __ LoadRoot(at, Heap::kNullValueRootIndex); |
| 5341 __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input)); | 5339 __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input)); |
| 5342 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | 5340 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 5343 __ GetObjectType(input, scratch, scratch1()); | 5341 __ GetObjectType(input, scratch, scratch1()); |
| 5344 __ Branch(false_label, lt, scratch1(), Operand(FIRST_JS_RECEIVER_TYPE)); | 5342 __ Branch(false_label, lt, scratch1(), Operand(FIRST_JS_RECEIVER_TYPE)); |
| 5345 // Check for callable or undetectable objects => false. | 5343 // Check for callable or undetectable objects => false. |
| 5346 __ lbu(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); | 5344 __ Lbu(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); |
| 5347 __ And(at, scratch, | 5345 __ And(at, scratch, |
| 5348 Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable))); | 5346 Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable))); |
| 5349 *cmp1 = at; | 5347 *cmp1 = at; |
| 5350 *cmp2 = Operand(zero_reg); | 5348 *cmp2 = Operand(zero_reg); |
| 5351 final_branch_condition = eq; | 5349 final_branch_condition = eq; |
| 5352 | 5350 |
| 5353 } else { | 5351 } else { |
| 5354 *cmp1 = at; | 5352 *cmp1 = at; |
| 5355 *cmp2 = Operand(zero_reg); // Set to valid regs, to avoid caller assertion. | 5353 *cmp2 = Operand(zero_reg); // Set to valid regs, to avoid caller assertion. |
| 5356 __ Branch(false_label); | 5354 __ Branch(false_label); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5485 | 5483 |
| 5486 | 5484 |
| 5487 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 5485 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
| 5488 Register result = ToRegister(instr->result()); | 5486 Register result = ToRegister(instr->result()); |
| 5489 Register object = ToRegister(instr->object()); | 5487 Register object = ToRegister(instr->object()); |
| 5490 | 5488 |
| 5491 Label use_cache, call_runtime; | 5489 Label use_cache, call_runtime; |
| 5492 DCHECK(object.is(a0)); | 5490 DCHECK(object.is(a0)); |
| 5493 __ CheckEnumCache(&call_runtime); | 5491 __ CheckEnumCache(&call_runtime); |
| 5494 | 5492 |
| 5495 __ ld(result, FieldMemOperand(object, HeapObject::kMapOffset)); | 5493 __ Ld(result, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 5496 __ Branch(&use_cache); | 5494 __ Branch(&use_cache); |
| 5497 | 5495 |
| 5498 // Get the set of properties to enumerate. | 5496 // Get the set of properties to enumerate. |
| 5499 __ bind(&call_runtime); | 5497 __ bind(&call_runtime); |
| 5500 __ push(object); | 5498 __ push(object); |
| 5501 CallRuntime(Runtime::kForInEnumerate, instr); | 5499 CallRuntime(Runtime::kForInEnumerate, instr); |
| 5502 __ bind(&use_cache); | 5500 __ bind(&use_cache); |
| 5503 } | 5501 } |
| 5504 | 5502 |
| 5505 | 5503 |
| 5506 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { | 5504 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { |
| 5507 Register map = ToRegister(instr->map()); | 5505 Register map = ToRegister(instr->map()); |
| 5508 Register result = ToRegister(instr->result()); | 5506 Register result = ToRegister(instr->result()); |
| 5509 Label load_cache, done; | 5507 Label load_cache, done; |
| 5510 __ EnumLength(result, map); | 5508 __ EnumLength(result, map); |
| 5511 __ Branch(&load_cache, ne, result, Operand(Smi::kZero)); | 5509 __ Branch(&load_cache, ne, result, Operand(Smi::kZero)); |
| 5512 __ li(result, Operand(isolate()->factory()->empty_fixed_array())); | 5510 __ li(result, Operand(isolate()->factory()->empty_fixed_array())); |
| 5513 __ jmp(&done); | 5511 __ jmp(&done); |
| 5514 | 5512 |
| 5515 __ bind(&load_cache); | 5513 __ bind(&load_cache); |
| 5516 __ LoadInstanceDescriptors(map, result); | 5514 __ LoadInstanceDescriptors(map, result); |
| 5517 __ ld(result, | 5515 __ Ld(result, FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); |
| 5518 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); | 5516 __ Ld(result, FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); |
| 5519 __ ld(result, | |
| 5520 FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); | |
| 5521 DeoptimizeIf(eq, instr, DeoptimizeReason::kNoCache, result, | 5517 DeoptimizeIf(eq, instr, DeoptimizeReason::kNoCache, result, |
| 5522 Operand(zero_reg)); | 5518 Operand(zero_reg)); |
| 5523 | 5519 |
| 5524 __ bind(&done); | 5520 __ bind(&done); |
| 5525 } | 5521 } |
| 5526 | 5522 |
| 5527 | 5523 |
| 5528 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { | 5524 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { |
| 5529 Register object = ToRegister(instr->value()); | 5525 Register object = ToRegister(instr->value()); |
| 5530 Register map = ToRegister(instr->map()); | 5526 Register map = ToRegister(instr->map()); |
| 5531 __ ld(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); | 5527 __ Ld(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); |
| 5532 DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongMap, map, | 5528 DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongMap, map, |
| 5533 Operand(scratch0())); | 5529 Operand(scratch0())); |
| 5534 } | 5530 } |
| 5535 | 5531 |
| 5536 | 5532 |
| 5537 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, | 5533 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, |
| 5538 Register result, | 5534 Register result, |
| 5539 Register object, | 5535 Register object, |
| 5540 Register index) { | 5536 Register index) { |
| 5541 PushSafepointRegistersScope scope(this); | 5537 PushSafepointRegistersScope scope(this); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5585 | 5581 |
| 5586 Label out_of_object, done; | 5582 Label out_of_object, done; |
| 5587 | 5583 |
| 5588 __ And(scratch, index, Operand(Smi::FromInt(1))); | 5584 __ And(scratch, index, Operand(Smi::FromInt(1))); |
| 5589 __ Branch(deferred->entry(), ne, scratch, Operand(zero_reg)); | 5585 __ Branch(deferred->entry(), ne, scratch, Operand(zero_reg)); |
| 5590 __ dsra(index, index, 1); | 5586 __ dsra(index, index, 1); |
| 5591 | 5587 |
| 5592 __ Branch(USE_DELAY_SLOT, &out_of_object, lt, index, Operand(zero_reg)); | 5588 __ Branch(USE_DELAY_SLOT, &out_of_object, lt, index, Operand(zero_reg)); |
| 5593 __ SmiScale(scratch, index, kPointerSizeLog2); // In delay slot. | 5589 __ SmiScale(scratch, index, kPointerSizeLog2); // In delay slot. |
| 5594 __ Daddu(scratch, object, scratch); | 5590 __ Daddu(scratch, object, scratch); |
| 5595 __ ld(result, FieldMemOperand(scratch, JSObject::kHeaderSize)); | 5591 __ Ld(result, FieldMemOperand(scratch, JSObject::kHeaderSize)); |
| 5596 | 5592 |
| 5597 __ Branch(&done); | 5593 __ Branch(&done); |
| 5598 | 5594 |
| 5599 __ bind(&out_of_object); | 5595 __ bind(&out_of_object); |
| 5600 __ ld(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 5596 __ Ld(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 5601 // Index is equal to negated out of object property index plus 1. | 5597 // Index is equal to negated out of object property index plus 1. |
| 5602 __ Dsubu(scratch, result, scratch); | 5598 __ Dsubu(scratch, result, scratch); |
| 5603 __ ld(result, FieldMemOperand(scratch, | 5599 __ Ld(result, |
| 5604 FixedArray::kHeaderSize - kPointerSize)); | 5600 FieldMemOperand(scratch, FixedArray::kHeaderSize - kPointerSize)); |
| 5605 __ bind(deferred->exit()); | 5601 __ bind(deferred->exit()); |
| 5606 __ bind(&done); | 5602 __ bind(&done); |
| 5607 } | 5603 } |
| 5608 | 5604 |
| 5609 #undef __ | 5605 #undef __ |
| 5610 | 5606 |
| 5611 } // namespace internal | 5607 } // namespace internal |
| 5612 } // namespace v8 | 5608 } // namespace v8 |
| OLD | NEW |