| 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 |