OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved.7 | 1 // Copyright 2012 the V8 project authors. All rights reserved.7 |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 | 108 |
109 | 109 |
110 void LCodeGen::SaveCallerDoubles() { | 110 void LCodeGen::SaveCallerDoubles() { |
111 DCHECK(info()->saves_caller_doubles()); | 111 DCHECK(info()->saves_caller_doubles()); |
112 DCHECK(NeedsEagerFrame()); | 112 DCHECK(NeedsEagerFrame()); |
113 Comment(";;; Save clobbered callee double registers"); | 113 Comment(";;; Save clobbered callee double registers"); |
114 int count = 0; | 114 int count = 0; |
115 BitVector* doubles = chunk()->allocated_double_registers(); | 115 BitVector* doubles = chunk()->allocated_double_registers(); |
116 BitVector::Iterator save_iterator(doubles); | 116 BitVector::Iterator save_iterator(doubles); |
117 while (!save_iterator.Done()) { | 117 while (!save_iterator.Done()) { |
118 __ sdc1(DoubleRegister::from_code(save_iterator.Current()), | 118 __ Sdc1(DoubleRegister::from_code(save_iterator.Current()), |
119 MemOperand(sp, count * kDoubleSize)); | 119 MemOperand(sp, count * kDoubleSize)); |
120 save_iterator.Advance(); | 120 save_iterator.Advance(); |
121 count++; | 121 count++; |
122 } | 122 } |
123 } | 123 } |
124 | 124 |
125 | 125 |
126 void LCodeGen::RestoreCallerDoubles() { | 126 void LCodeGen::RestoreCallerDoubles() { |
127 DCHECK(info()->saves_caller_doubles()); | 127 DCHECK(info()->saves_caller_doubles()); |
128 DCHECK(NeedsEagerFrame()); | 128 DCHECK(NeedsEagerFrame()); |
129 Comment(";;; Restore clobbered callee double registers"); | 129 Comment(";;; Restore clobbered callee double registers"); |
130 BitVector* doubles = chunk()->allocated_double_registers(); | 130 BitVector* doubles = chunk()->allocated_double_registers(); |
131 BitVector::Iterator save_iterator(doubles); | 131 BitVector::Iterator save_iterator(doubles); |
132 int count = 0; | 132 int count = 0; |
133 while (!save_iterator.Done()) { | 133 while (!save_iterator.Done()) { |
134 __ ldc1(DoubleRegister::from_code(save_iterator.Current()), | 134 __ Ldc1(DoubleRegister::from_code(save_iterator.Current()), |
135 MemOperand(sp, count * kDoubleSize)); | 135 MemOperand(sp, count * kDoubleSize)); |
136 save_iterator.Advance(); | 136 save_iterator.Advance(); |
137 count++; | 137 count++; |
138 } | 138 } |
139 } | 139 } |
140 | 140 |
141 | 141 |
142 bool LCodeGen::GeneratePrologue() { | 142 bool LCodeGen::GeneratePrologue() { |
143 DCHECK(is_generating()); | 143 DCHECK(is_generating()); |
144 | 144 |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 __ mtc1(at, flt_scratch); | 465 __ mtc1(at, flt_scratch); |
466 __ cvt_d_w(dbl_scratch, flt_scratch); | 466 __ cvt_d_w(dbl_scratch, flt_scratch); |
467 return dbl_scratch; | 467 return dbl_scratch; |
468 } else if (r.IsDouble()) { | 468 } else if (r.IsDouble()) { |
469 Abort(kUnsupportedDoubleImmediate); | 469 Abort(kUnsupportedDoubleImmediate); |
470 } else if (r.IsTagged()) { | 470 } else if (r.IsTagged()) { |
471 Abort(kUnsupportedTaggedImmediate); | 471 Abort(kUnsupportedTaggedImmediate); |
472 } | 472 } |
473 } else if (op->IsStackSlot()) { | 473 } else if (op->IsStackSlot()) { |
474 MemOperand mem_op = ToMemOperand(op); | 474 MemOperand mem_op = ToMemOperand(op); |
475 __ ldc1(dbl_scratch, mem_op); | 475 __ Ldc1(dbl_scratch, mem_op); |
476 return dbl_scratch; | 476 return dbl_scratch; |
477 } | 477 } |
478 UNREACHABLE(); | 478 UNREACHABLE(); |
479 return dbl_scratch; | 479 return dbl_scratch; |
480 } | 480 } |
481 | 481 |
482 | 482 |
483 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { | 483 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { |
484 HConstant* constant = chunk_->LookupConstant(op); | 484 HConstant* constant = chunk_->LookupConstant(op); |
485 DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); | 485 DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); |
(...skipping 1456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1942 EmitBranch(instr, eq, reg, Operand(at)); | 1942 EmitBranch(instr, eq, reg, Operand(at)); |
1943 } else if (type.IsSmi()) { | 1943 } else if (type.IsSmi()) { |
1944 DCHECK(!info()->IsStub()); | 1944 DCHECK(!info()->IsStub()); |
1945 EmitBranch(instr, ne, reg, Operand(zero_reg)); | 1945 EmitBranch(instr, ne, reg, Operand(zero_reg)); |
1946 } else if (type.IsJSArray()) { | 1946 } else if (type.IsJSArray()) { |
1947 DCHECK(!info()->IsStub()); | 1947 DCHECK(!info()->IsStub()); |
1948 EmitBranch(instr, al, zero_reg, Operand(zero_reg)); | 1948 EmitBranch(instr, al, zero_reg, Operand(zero_reg)); |
1949 } else if (type.IsHeapNumber()) { | 1949 } else if (type.IsHeapNumber()) { |
1950 DCHECK(!info()->IsStub()); | 1950 DCHECK(!info()->IsStub()); |
1951 DoubleRegister dbl_scratch = double_scratch0(); | 1951 DoubleRegister dbl_scratch = double_scratch0(); |
1952 __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 1952 __ Ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
1953 // Test the double value. Zero and NaN are false. | 1953 // Test the double value. Zero and NaN are false. |
1954 EmitBranchF(instr, ogl, dbl_scratch, kDoubleRegZero); | 1954 EmitBranchF(instr, ogl, dbl_scratch, kDoubleRegZero); |
1955 } else if (type.IsString()) { | 1955 } else if (type.IsString()) { |
1956 DCHECK(!info()->IsStub()); | 1956 DCHECK(!info()->IsStub()); |
1957 __ lw(at, FieldMemOperand(reg, String::kLengthOffset)); | 1957 __ lw(at, FieldMemOperand(reg, String::kLengthOffset)); |
1958 EmitBranch(instr, ne, at, Operand(zero_reg)); | 1958 EmitBranch(instr, ne, at, Operand(zero_reg)); |
1959 } else { | 1959 } else { |
1960 ToBooleanHints expected = instr->hydrogen()->expected_input_types(); | 1960 ToBooleanHints expected = instr->hydrogen()->expected_input_types(); |
1961 // Avoid deopts in the case where we've never executed this path before. | 1961 // Avoid deopts in the case where we've never executed this path before. |
1962 if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny; | 1962 if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2024 __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 2024 __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
2025 __ Branch(instr->TrueLabel(chunk_), eq, scratch, Operand(SYMBOL_TYPE)); | 2025 __ Branch(instr->TrueLabel(chunk_), eq, scratch, Operand(SYMBOL_TYPE)); |
2026 } | 2026 } |
2027 | 2027 |
2028 if (expected & ToBooleanHint::kHeapNumber) { | 2028 if (expected & ToBooleanHint::kHeapNumber) { |
2029 // heap number -> false iff +0, -0, or NaN. | 2029 // heap number -> false iff +0, -0, or NaN. |
2030 DoubleRegister dbl_scratch = double_scratch0(); | 2030 DoubleRegister dbl_scratch = double_scratch0(); |
2031 Label not_heap_number; | 2031 Label not_heap_number; |
2032 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 2032 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
2033 __ Branch(¬_heap_number, ne, map, Operand(at)); | 2033 __ Branch(¬_heap_number, ne, map, Operand(at)); |
2034 __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 2034 __ Ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
2035 __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), | 2035 __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
2036 ne, dbl_scratch, kDoubleRegZero); | 2036 ne, dbl_scratch, kDoubleRegZero); |
2037 // Falls through if dbl_scratch == 0. | 2037 // Falls through if dbl_scratch == 0. |
2038 __ Branch(instr->FalseLabel(chunk_)); | 2038 __ Branch(instr->FalseLabel(chunk_)); |
2039 __ bind(¬_heap_number); | 2039 __ bind(¬_heap_number); |
2040 } | 2040 } |
2041 | 2041 |
2042 if (expected != ToBooleanHint::kAny) { | 2042 if (expected != ToBooleanHint::kAny) { |
2043 // We've seen something for the first time -> deopt. | 2043 // We've seen something for the first time -> deopt. |
2044 // This can only happen if we are not generic already. | 2044 // This can only happen if we are not generic already. |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2474 | 2474 |
2475 if (access.IsExternalMemory()) { | 2475 if (access.IsExternalMemory()) { |
2476 Register result = ToRegister(instr->result()); | 2476 Register result = ToRegister(instr->result()); |
2477 MemOperand operand = MemOperand(object, offset); | 2477 MemOperand operand = MemOperand(object, offset); |
2478 __ Load(result, operand, access.representation()); | 2478 __ Load(result, operand, access.representation()); |
2479 return; | 2479 return; |
2480 } | 2480 } |
2481 | 2481 |
2482 if (instr->hydrogen()->representation().IsDouble()) { | 2482 if (instr->hydrogen()->representation().IsDouble()) { |
2483 DoubleRegister result = ToDoubleRegister(instr->result()); | 2483 DoubleRegister result = ToDoubleRegister(instr->result()); |
2484 __ ldc1(result, FieldMemOperand(object, offset)); | 2484 __ Ldc1(result, FieldMemOperand(object, offset)); |
2485 return; | 2485 return; |
2486 } | 2486 } |
2487 | 2487 |
2488 Register result = ToRegister(instr->result()); | 2488 Register result = ToRegister(instr->result()); |
2489 if (!access.IsInobject()) { | 2489 if (!access.IsInobject()) { |
2490 __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 2490 __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
2491 object = result; | 2491 object = result; |
2492 } | 2492 } |
2493 MemOperand operand = FieldMemOperand(object, offset); | 2493 MemOperand operand = FieldMemOperand(object, offset); |
2494 __ Load(result, operand, access.representation()); | 2494 __ Load(result, operand, access.representation()); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2592 if (key_is_constant) { | 2592 if (key_is_constant) { |
2593 __ Addu(scratch0(), external_pointer, constant_key << element_size_shift); | 2593 __ Addu(scratch0(), external_pointer, constant_key << element_size_shift); |
2594 } else { | 2594 } else { |
2595 __ sll(scratch0(), key, shift_size); | 2595 __ sll(scratch0(), key, shift_size); |
2596 __ Addu(scratch0(), scratch0(), external_pointer); | 2596 __ Addu(scratch0(), scratch0(), external_pointer); |
2597 } | 2597 } |
2598 if (elements_kind == FLOAT32_ELEMENTS) { | 2598 if (elements_kind == FLOAT32_ELEMENTS) { |
2599 __ lwc1(result, MemOperand(scratch0(), base_offset)); | 2599 __ lwc1(result, MemOperand(scratch0(), base_offset)); |
2600 __ cvt_d_s(result, result); | 2600 __ cvt_d_s(result, result); |
2601 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS | 2601 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
2602 __ ldc1(result, MemOperand(scratch0(), base_offset)); | 2602 __ Ldc1(result, MemOperand(scratch0(), base_offset)); |
2603 } | 2603 } |
2604 } else { | 2604 } else { |
2605 Register result = ToRegister(instr->result()); | 2605 Register result = ToRegister(instr->result()); |
2606 MemOperand mem_operand = PrepareKeyedOperand( | 2606 MemOperand mem_operand = PrepareKeyedOperand( |
2607 key, external_pointer, key_is_constant, constant_key, | 2607 key, external_pointer, key_is_constant, constant_key, |
2608 element_size_shift, shift_size, base_offset); | 2608 element_size_shift, shift_size, base_offset); |
2609 switch (elements_kind) { | 2609 switch (elements_kind) { |
2610 case INT8_ELEMENTS: | 2610 case INT8_ELEMENTS: |
2611 __ lb(result, mem_operand); | 2611 __ lb(result, mem_operand); |
2612 break; | 2612 break; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2670 } | 2670 } |
2671 __ Addu(scratch, elements, Operand(base_offset)); | 2671 __ Addu(scratch, elements, Operand(base_offset)); |
2672 | 2672 |
2673 if (!key_is_constant) { | 2673 if (!key_is_constant) { |
2674 key = ToRegister(instr->key()); | 2674 key = ToRegister(instr->key()); |
2675 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) | 2675 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
2676 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 2676 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
2677 __ Lsa(scratch, scratch, key, shift_size); | 2677 __ Lsa(scratch, scratch, key, shift_size); |
2678 } | 2678 } |
2679 | 2679 |
2680 __ ldc1(result, MemOperand(scratch)); | 2680 __ Ldc1(result, MemOperand(scratch)); |
2681 | 2681 |
2682 if (instr->hydrogen()->RequiresHoleCheck()) { | 2682 if (instr->hydrogen()->RequiresHoleCheck()) { |
2683 __ lw(scratch, MemOperand(scratch, kHoleNanUpper32Offset)); | 2683 __ lw(scratch, MemOperand(scratch, kHoleNanUpper32Offset)); |
2684 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, scratch, | 2684 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, scratch, |
2685 Operand(kHoleNanUpper32)); | 2685 Operand(kHoleNanUpper32)); |
2686 } | 2686 } |
2687 } | 2687 } |
2688 | 2688 |
2689 | 2689 |
2690 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 2690 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
(...skipping 906 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3597 __ AssertNotSmi(object); | 3597 __ AssertNotSmi(object); |
3598 | 3598 |
3599 DCHECK(!representation.IsSmi() || | 3599 DCHECK(!representation.IsSmi() || |
3600 !instr->value()->IsConstantOperand() || | 3600 !instr->value()->IsConstantOperand() || |
3601 IsSmi(LConstantOperand::cast(instr->value()))); | 3601 IsSmi(LConstantOperand::cast(instr->value()))); |
3602 if (representation.IsDouble()) { | 3602 if (representation.IsDouble()) { |
3603 DCHECK(access.IsInobject()); | 3603 DCHECK(access.IsInobject()); |
3604 DCHECK(!instr->hydrogen()->has_transition()); | 3604 DCHECK(!instr->hydrogen()->has_transition()); |
3605 DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); | 3605 DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); |
3606 DoubleRegister value = ToDoubleRegister(instr->value()); | 3606 DoubleRegister value = ToDoubleRegister(instr->value()); |
3607 __ sdc1(value, FieldMemOperand(object, offset)); | 3607 __ Sdc1(value, FieldMemOperand(object, offset)); |
3608 return; | 3608 return; |
3609 } | 3609 } |
3610 | 3610 |
3611 if (instr->hydrogen()->has_transition()) { | 3611 if (instr->hydrogen()->has_transition()) { |
3612 Handle<Map> transition = instr->hydrogen()->transition_map(); | 3612 Handle<Map> transition = instr->hydrogen()->transition_map(); |
3613 AddDeprecationDependency(transition); | 3613 AddDeprecationDependency(transition); |
3614 __ li(scratch, Operand(transition)); | 3614 __ li(scratch, Operand(transition)); |
3615 __ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 3615 __ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
3616 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { | 3616 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { |
3617 Register temp = ToRegister(instr->temp()); | 3617 Register temp = ToRegister(instr->temp()); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3715 address = external_pointer; | 3715 address = external_pointer; |
3716 } | 3716 } |
3717 } else { | 3717 } else { |
3718 __ Lsa(address, external_pointer, key, shift_size); | 3718 __ Lsa(address, external_pointer, key, shift_size); |
3719 } | 3719 } |
3720 | 3720 |
3721 if (elements_kind == FLOAT32_ELEMENTS) { | 3721 if (elements_kind == FLOAT32_ELEMENTS) { |
3722 __ cvt_s_d(double_scratch0(), value); | 3722 __ cvt_s_d(double_scratch0(), value); |
3723 __ swc1(double_scratch0(), MemOperand(address, base_offset)); | 3723 __ swc1(double_scratch0(), MemOperand(address, base_offset)); |
3724 } else { // Storing doubles, not floats. | 3724 } else { // Storing doubles, not floats. |
3725 __ sdc1(value, MemOperand(address, base_offset)); | 3725 __ Sdc1(value, MemOperand(address, base_offset)); |
3726 } | 3726 } |
3727 } else { | 3727 } else { |
3728 Register value(ToRegister(instr->value())); | 3728 Register value(ToRegister(instr->value())); |
3729 MemOperand mem_operand = PrepareKeyedOperand( | 3729 MemOperand mem_operand = PrepareKeyedOperand( |
3730 key, external_pointer, key_is_constant, constant_key, | 3730 key, external_pointer, key_is_constant, constant_key, |
3731 element_size_shift, shift_size, | 3731 element_size_shift, shift_size, |
3732 base_offset); | 3732 base_offset); |
3733 switch (elements_kind) { | 3733 switch (elements_kind) { |
3734 case UINT8_ELEMENTS: | 3734 case UINT8_ELEMENTS: |
3735 case UINT8_CLAMPED_ELEMENTS: | 3735 case UINT8_CLAMPED_ELEMENTS: |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3795 | 3795 |
3796 if (instr->NeedsCanonicalization()) { | 3796 if (instr->NeedsCanonicalization()) { |
3797 Label is_nan; | 3797 Label is_nan; |
3798 // Check for NaN. All NaNs must be canonicalized. | 3798 // Check for NaN. All NaNs must be canonicalized. |
3799 __ BranchF(NULL, &is_nan, eq, value, value); | 3799 __ BranchF(NULL, &is_nan, eq, value, value); |
3800 __ Branch(¬_nan); | 3800 __ Branch(¬_nan); |
3801 | 3801 |
3802 // Only load canonical NaN if the comparison above set the overflow. | 3802 // Only load canonical NaN if the comparison above set the overflow. |
3803 __ bind(&is_nan); | 3803 __ bind(&is_nan); |
3804 __ LoadRoot(scratch_1, Heap::kNanValueRootIndex); | 3804 __ LoadRoot(scratch_1, Heap::kNanValueRootIndex); |
3805 __ ldc1(double_scratch, | 3805 __ Ldc1(double_scratch, |
3806 FieldMemOperand(scratch_1, HeapNumber::kValueOffset)); | 3806 FieldMemOperand(scratch_1, HeapNumber::kValueOffset)); |
3807 __ sdc1(double_scratch, MemOperand(scratch, 0)); | 3807 __ Sdc1(double_scratch, MemOperand(scratch, 0)); |
3808 __ Branch(&done); | 3808 __ Branch(&done); |
3809 } | 3809 } |
3810 | 3810 |
3811 __ bind(¬_nan); | 3811 __ bind(¬_nan); |
3812 __ sdc1(value, MemOperand(scratch, 0)); | 3812 __ Sdc1(value, MemOperand(scratch, 0)); |
3813 __ bind(&done); | 3813 __ bind(&done); |
3814 } | 3814 } |
3815 | 3815 |
3816 | 3816 |
3817 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { | 3817 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
3818 Register value = ToRegister(instr->value()); | 3818 Register value = ToRegister(instr->value()); |
3819 Register elements = ToRegister(instr->elements()); | 3819 Register elements = ToRegister(instr->elements()); |
3820 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) | 3820 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) |
3821 : no_reg; | 3821 : no_reg; |
3822 Register scratch = scratch0(); | 3822 Register scratch = scratch0(); |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4275 } | 4275 } |
4276 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 4276 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
4277 RecordSafepointWithRegisters( | 4277 RecordSafepointWithRegisters( |
4278 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4278 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
4279 __ StoreToSafepointRegisterSlot(v0, dst); | 4279 __ StoreToSafepointRegisterSlot(v0, dst); |
4280 } | 4280 } |
4281 | 4281 |
4282 // Done. Put the value in dbl_scratch into the value of the allocated heap | 4282 // Done. Put the value in dbl_scratch into the value of the allocated heap |
4283 // number. | 4283 // number. |
4284 __ bind(&done); | 4284 __ bind(&done); |
4285 __ sdc1(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset)); | 4285 __ Sdc1(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset)); |
4286 } | 4286 } |
4287 | 4287 |
4288 | 4288 |
4289 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 4289 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
4290 class DeferredNumberTagD final : public LDeferredCode { | 4290 class DeferredNumberTagD final : public LDeferredCode { |
4291 public: | 4291 public: |
4292 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4292 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
4293 : LDeferredCode(codegen), instr_(instr) { } | 4293 : LDeferredCode(codegen), instr_(instr) { } |
4294 void Generate() override { codegen()->DoDeferredNumberTagD(instr_); } | 4294 void Generate() override { codegen()->DoDeferredNumberTagD(instr_); } |
4295 LInstruction* instr() override { return instr_; } | 4295 LInstruction* instr() override { return instr_; } |
4296 | 4296 |
4297 private: | 4297 private: |
4298 LNumberTagD* instr_; | 4298 LNumberTagD* instr_; |
4299 }; | 4299 }; |
4300 | 4300 |
4301 DoubleRegister input_reg = ToDoubleRegister(instr->value()); | 4301 DoubleRegister input_reg = ToDoubleRegister(instr->value()); |
4302 Register scratch = scratch0(); | 4302 Register scratch = scratch0(); |
4303 Register reg = ToRegister(instr->result()); | 4303 Register reg = ToRegister(instr->result()); |
4304 Register temp1 = ToRegister(instr->temp()); | 4304 Register temp1 = ToRegister(instr->temp()); |
4305 Register temp2 = ToRegister(instr->temp2()); | 4305 Register temp2 = ToRegister(instr->temp2()); |
4306 | 4306 |
4307 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4307 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
4308 if (FLAG_inline_new) { | 4308 if (FLAG_inline_new) { |
4309 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 4309 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
4310 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); | 4310 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); |
4311 } else { | 4311 } else { |
4312 __ Branch(deferred->entry()); | 4312 __ Branch(deferred->entry()); |
4313 } | 4313 } |
4314 __ bind(deferred->exit()); | 4314 __ bind(deferred->exit()); |
4315 __ sdc1(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 4315 __ Sdc1(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
4316 // Now that we have finished with the object's real address tag it | 4316 // Now that we have finished with the object's real address tag it |
4317 } | 4317 } |
4318 | 4318 |
4319 | 4319 |
4320 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4320 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
4321 // TODO(3095996): Get rid of this. For now, we need to make the | 4321 // TODO(3095996): Get rid of this. For now, we need to make the |
4322 // result register contain a valid pointer because it is already | 4322 // result register contain a valid pointer because it is already |
4323 // contained in the register pointer map. | 4323 // contained in the register pointer map. |
4324 Register reg = ToRegister(instr->result()); | 4324 Register reg = ToRegister(instr->result()); |
4325 __ mov(reg, zero_reg); | 4325 __ mov(reg, zero_reg); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4386 // Heap number map check. | 4386 // Heap number map check. |
4387 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4387 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
4388 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 4388 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
4389 if (can_convert_undefined_to_nan) { | 4389 if (can_convert_undefined_to_nan) { |
4390 __ Branch(&convert, ne, scratch, Operand(at)); | 4390 __ Branch(&convert, ne, scratch, Operand(at)); |
4391 } else { | 4391 } else { |
4392 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch, | 4392 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch, |
4393 Operand(at)); | 4393 Operand(at)); |
4394 } | 4394 } |
4395 // Load heap number. | 4395 // Load heap number. |
4396 __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 4396 __ Ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
4397 if (deoptimize_on_minus_zero) { | 4397 if (deoptimize_on_minus_zero) { |
4398 __ mfc1(at, result_reg.low()); | 4398 __ mfc1(at, result_reg.low()); |
4399 __ Branch(&done, ne, at, Operand(zero_reg)); | 4399 __ Branch(&done, ne, at, Operand(zero_reg)); |
4400 __ Mfhc1(scratch, result_reg); | 4400 __ Mfhc1(scratch, result_reg); |
4401 DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, scratch, | 4401 DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, scratch, |
4402 Operand(HeapNumber::kSignMask)); | 4402 Operand(HeapNumber::kSignMask)); |
4403 } | 4403 } |
4404 __ Branch(&done); | 4404 __ Branch(&done); |
4405 if (can_convert_undefined_to_nan) { | 4405 if (can_convert_undefined_to_nan) { |
4406 __ bind(&convert); | 4406 __ bind(&convert); |
4407 // Convert undefined (and hole) to NaN. | 4407 // Convert undefined (and hole) to NaN. |
4408 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 4408 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
4409 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined, | 4409 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined, |
4410 input_reg, Operand(at)); | 4410 input_reg, Operand(at)); |
4411 __ LoadRoot(scratch, Heap::kNanValueRootIndex); | 4411 __ LoadRoot(scratch, Heap::kNanValueRootIndex); |
4412 __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset)); | 4412 __ Ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset)); |
4413 __ Branch(&done); | 4413 __ Branch(&done); |
4414 } | 4414 } |
4415 } else { | 4415 } else { |
4416 __ SmiUntag(scratch, input_reg); | 4416 __ SmiUntag(scratch, input_reg); |
4417 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); | 4417 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); |
4418 } | 4418 } |
4419 // Smi to double register conversion | 4419 // Smi to double register conversion |
4420 __ bind(&load_smi); | 4420 __ bind(&load_smi); |
4421 // scratch: untagged value of input_reg | 4421 // scratch: untagged value of input_reg |
4422 __ mtc1(scratch, result_reg); | 4422 __ mtc1(scratch, result_reg); |
(...skipping 28 matching lines...) Expand all Loading... |
4451 __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | 4451 __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
4452 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotANumberOrOddball, scratch1, | 4452 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotANumberOrOddball, scratch1, |
4453 Operand(ODDBALL_TYPE)); | 4453 Operand(ODDBALL_TYPE)); |
4454 __ bind(&truncate); | 4454 __ bind(&truncate); |
4455 __ TruncateHeapNumberToI(input_reg, scratch2); | 4455 __ TruncateHeapNumberToI(input_reg, scratch2); |
4456 } else { | 4456 } else { |
4457 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch1, | 4457 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch1, |
4458 Operand(at)); | 4458 Operand(at)); |
4459 | 4459 |
4460 // Load the double value. | 4460 // Load the double value. |
4461 __ ldc1(double_scratch, | 4461 __ Ldc1(double_scratch, |
4462 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 4462 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
4463 | 4463 |
4464 Register except_flag = scratch2; | 4464 Register except_flag = scratch2; |
4465 __ EmitFPUTruncate(kRoundToZero, | 4465 __ EmitFPUTruncate(kRoundToZero, |
4466 input_reg, | 4466 input_reg, |
4467 double_scratch, | 4467 double_scratch, |
4468 scratch1, | 4468 scratch1, |
4469 double_scratch2, | 4469 double_scratch2, |
4470 except_flag, | 4470 except_flag, |
4471 kCheckForInexactConversion); | 4471 kCheckForInexactConversion); |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4816 | 4816 |
4817 // Check for undefined. Undefined is converted to zero for clamping | 4817 // Check for undefined. Undefined is converted to zero for clamping |
4818 // conversions. | 4818 // conversions. |
4819 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined, input_reg, | 4819 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined, input_reg, |
4820 Operand(factory()->undefined_value())); | 4820 Operand(factory()->undefined_value())); |
4821 __ mov(result_reg, zero_reg); | 4821 __ mov(result_reg, zero_reg); |
4822 __ jmp(&done); | 4822 __ jmp(&done); |
4823 | 4823 |
4824 // Heap number | 4824 // Heap number |
4825 __ bind(&heap_number); | 4825 __ bind(&heap_number); |
4826 __ ldc1(double_scratch0(), FieldMemOperand(input_reg, | 4826 __ Ldc1(double_scratch0(), |
4827 HeapNumber::kValueOffset)); | 4827 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
4828 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); | 4828 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); |
4829 __ jmp(&done); | 4829 __ jmp(&done); |
4830 | 4830 |
4831 __ bind(&is_smi); | 4831 __ bind(&is_smi); |
4832 __ ClampUint8(result_reg, scratch); | 4832 __ ClampUint8(result_reg, scratch); |
4833 | 4833 |
4834 __ bind(&done); | 4834 __ bind(&done); |
4835 } | 4835 } |
4836 | 4836 |
4837 | 4837 |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5356 __ lw(result, FieldMemOperand(scratch, | 5356 __ lw(result, FieldMemOperand(scratch, |
5357 FixedArray::kHeaderSize - kPointerSize)); | 5357 FixedArray::kHeaderSize - kPointerSize)); |
5358 __ bind(deferred->exit()); | 5358 __ bind(deferred->exit()); |
5359 __ bind(&done); | 5359 __ bind(&done); |
5360 } | 5360 } |
5361 | 5361 |
5362 #undef __ | 5362 #undef __ |
5363 | 5363 |
5364 } // namespace internal | 5364 } // namespace internal |
5365 } // namespace v8 | 5365 } // namespace v8 |
OLD | NEW |