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/arm/lithium-codegen-arm.h" | 5 #include "src/crankshaft/arm/lithium-codegen-arm.h" |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.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/arm/lithium-gap-resolver-arm.h" | 10 #include "src/crankshaft/arm/lithium-gap-resolver-arm.h" |
(...skipping 4478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4489 } | 4489 } |
4490 __ vmov(dbl_scratch.low(), src); | 4490 __ vmov(dbl_scratch.low(), src); |
4491 __ vcvt_f64_s32(dbl_scratch, dbl_scratch.low()); | 4491 __ vcvt_f64_s32(dbl_scratch, dbl_scratch.low()); |
4492 } else { | 4492 } else { |
4493 __ vmov(dbl_scratch.low(), src); | 4493 __ vmov(dbl_scratch.low(), src); |
4494 __ vcvt_f64_u32(dbl_scratch, dbl_scratch.low()); | 4494 __ vcvt_f64_u32(dbl_scratch, dbl_scratch.low()); |
4495 } | 4495 } |
4496 | 4496 |
4497 if (FLAG_inline_new) { | 4497 if (FLAG_inline_new) { |
4498 __ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex); | 4498 __ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex); |
4499 __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow, DONT_TAG_RESULT); | 4499 __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow); |
4500 __ b(&done); | 4500 __ b(&done); |
4501 } | 4501 } |
4502 | 4502 |
4503 // Slow case: Call the runtime system to do the number allocation. | 4503 // Slow case: Call the runtime system to do the number allocation. |
4504 __ bind(&slow); | 4504 __ bind(&slow); |
4505 { | 4505 { |
4506 // TODO(3095996): Put a valid pointer value in the stack slot where the | 4506 // TODO(3095996): Put a valid pointer value in the stack slot where the |
4507 // result register is stored, as this register is in the pointer map, but | 4507 // result register is stored, as this register is in the pointer map, but |
4508 // contains an integer value. | 4508 // contains an integer value. |
4509 __ mov(dst, Operand::Zero()); | 4509 __ mov(dst, Operand::Zero()); |
4510 | 4510 |
4511 // Preserve the value of all registers. | 4511 // Preserve the value of all registers. |
4512 PushSafepointRegistersScope scope(this); | 4512 PushSafepointRegistersScope scope(this); |
4513 | 4513 |
4514 // NumberTagI and NumberTagD use the context from the frame, rather than | 4514 // NumberTagI and NumberTagD use the context from the frame, rather than |
4515 // the environment's HContext or HInlinedContext value. | 4515 // the environment's HContext or HInlinedContext value. |
4516 // They only call Runtime::kAllocateHeapNumber. | 4516 // They only call Runtime::kAllocateHeapNumber. |
4517 // The corresponding HChange instructions are added in a phase that does | 4517 // The corresponding HChange instructions are added in a phase that does |
4518 // not have easy access to the local context. | 4518 // not have easy access to the local context. |
4519 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4519 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
4520 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 4520 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
4521 RecordSafepointWithRegisters( | 4521 RecordSafepointWithRegisters( |
4522 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4522 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
4523 __ sub(r0, r0, Operand(kHeapObjectTag)); | |
4524 __ StoreToSafepointRegisterSlot(r0, dst); | 4523 __ StoreToSafepointRegisterSlot(r0, dst); |
4525 } | 4524 } |
4526 | 4525 |
4527 // Done. Put the value in dbl_scratch into the value of the allocated heap | 4526 // Done. Put the value in dbl_scratch into the value of the allocated heap |
4528 // number. | 4527 // number. |
4529 __ bind(&done); | 4528 __ bind(&done); |
4530 __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); | 4529 __ vstr(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset)); |
4531 __ add(dst, dst, Operand(kHeapObjectTag)); | |
4532 } | 4530 } |
4533 | 4531 |
4534 | 4532 |
4535 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 4533 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
4536 class DeferredNumberTagD final : public LDeferredCode { | 4534 class DeferredNumberTagD final : public LDeferredCode { |
4537 public: | 4535 public: |
4538 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4536 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
4539 : LDeferredCode(codegen), instr_(instr) { } | 4537 : LDeferredCode(codegen), instr_(instr) { } |
4540 void Generate() override { codegen()->DoDeferredNumberTagD(instr_); } | 4538 void Generate() override { codegen()->DoDeferredNumberTagD(instr_); } |
4541 LInstruction* instr() override { return instr_; } | 4539 LInstruction* instr() override { return instr_; } |
4542 | 4540 |
4543 private: | 4541 private: |
4544 LNumberTagD* instr_; | 4542 LNumberTagD* instr_; |
4545 }; | 4543 }; |
4546 | 4544 |
4547 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); | 4545 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); |
4548 Register scratch = scratch0(); | 4546 Register scratch = scratch0(); |
4549 Register reg = ToRegister(instr->result()); | 4547 Register reg = ToRegister(instr->result()); |
4550 Register temp1 = ToRegister(instr->temp()); | 4548 Register temp1 = ToRegister(instr->temp()); |
4551 Register temp2 = ToRegister(instr->temp2()); | 4549 Register temp2 = ToRegister(instr->temp2()); |
4552 | 4550 |
4553 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4551 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
4554 if (FLAG_inline_new) { | 4552 if (FLAG_inline_new) { |
4555 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 4553 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
4556 // We want the untagged address first for performance | 4554 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); |
4557 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), | |
4558 DONT_TAG_RESULT); | |
4559 } else { | 4555 } else { |
4560 __ jmp(deferred->entry()); | 4556 __ jmp(deferred->entry()); |
4561 } | 4557 } |
4562 __ bind(deferred->exit()); | 4558 __ bind(deferred->exit()); |
4563 __ vstr(input_reg, reg, HeapNumber::kValueOffset); | 4559 __ vstr(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
4564 // Now that we have finished with the object's real address tag it | |
4565 __ add(reg, reg, Operand(kHeapObjectTag)); | |
4566 } | 4560 } |
4567 | 4561 |
4568 | 4562 |
4569 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4563 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
4570 // TODO(3095996): Get rid of this. For now, we need to make the | 4564 // TODO(3095996): Get rid of this. For now, we need to make the |
4571 // result register contain a valid pointer because it is already | 4565 // result register contain a valid pointer because it is already |
4572 // contained in the register pointer map. | 4566 // contained in the register pointer map. |
4573 Register reg = ToRegister(instr->result()); | 4567 Register reg = ToRegister(instr->result()); |
4574 __ mov(reg, Operand::Zero()); | 4568 __ mov(reg, Operand::Zero()); |
4575 | 4569 |
4576 PushSafepointRegistersScope scope(this); | 4570 PushSafepointRegistersScope scope(this); |
4577 // NumberTagI and NumberTagD use the context from the frame, rather than | 4571 // NumberTagI and NumberTagD use the context from the frame, rather than |
4578 // the environment's HContext or HInlinedContext value. | 4572 // the environment's HContext or HInlinedContext value. |
4579 // They only call Runtime::kAllocateHeapNumber. | 4573 // They only call Runtime::kAllocateHeapNumber. |
4580 // The corresponding HChange instructions are added in a phase that does | 4574 // The corresponding HChange instructions are added in a phase that does |
4581 // not have easy access to the local context. | 4575 // not have easy access to the local context. |
4582 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4576 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
4583 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 4577 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
4584 RecordSafepointWithRegisters( | 4578 RecordSafepointWithRegisters( |
4585 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4579 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
4586 __ sub(r0, r0, Operand(kHeapObjectTag)); | |
4587 __ StoreToSafepointRegisterSlot(r0, reg); | 4580 __ StoreToSafepointRegisterSlot(r0, reg); |
4588 } | 4581 } |
4589 | 4582 |
4590 | 4583 |
4591 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4584 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
4592 HChange* hchange = instr->hydrogen(); | 4585 HChange* hchange = instr->hydrogen(); |
4593 Register input = ToRegister(instr->value()); | 4586 Register input = ToRegister(instr->value()); |
4594 Register output = ToRegister(instr->result()); | 4587 Register output = ToRegister(instr->result()); |
4595 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4588 if (hchange->CheckFlag(HValue::kCanOverflow) && |
4596 hchange->value()->CheckFlag(HValue::kUint32)) { | 4589 hchange->value()->CheckFlag(HValue::kUint32)) { |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5100 }; | 5093 }; |
5101 | 5094 |
5102 DeferredAllocate* deferred = | 5095 DeferredAllocate* deferred = |
5103 new(zone()) DeferredAllocate(this, instr); | 5096 new(zone()) DeferredAllocate(this, instr); |
5104 | 5097 |
5105 Register result = ToRegister(instr->result()); | 5098 Register result = ToRegister(instr->result()); |
5106 Register scratch = ToRegister(instr->temp1()); | 5099 Register scratch = ToRegister(instr->temp1()); |
5107 Register scratch2 = ToRegister(instr->temp2()); | 5100 Register scratch2 = ToRegister(instr->temp2()); |
5108 | 5101 |
5109 // Allocate memory for the object. | 5102 // Allocate memory for the object. |
5110 AllocationFlags flags = TAG_OBJECT; | 5103 AllocationFlags flags = NO_ALLOCATION_FLAGS; |
5111 if (instr->hydrogen()->MustAllocateDoubleAligned()) { | 5104 if (instr->hydrogen()->MustAllocateDoubleAligned()) { |
5112 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); | 5105 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); |
5113 } | 5106 } |
5114 if (instr->hydrogen()->IsOldSpaceAllocation()) { | 5107 if (instr->hydrogen()->IsOldSpaceAllocation()) { |
5115 DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); | 5108 DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); |
5116 flags = static_cast<AllocationFlags>(flags | PRETENURE); | 5109 flags = static_cast<AllocationFlags>(flags | PRETENURE); |
5117 } | 5110 } |
5118 | 5111 |
5119 if (instr->size()->IsConstantOperand()) { | 5112 if (instr->size()->IsConstantOperand()) { |
5120 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5113 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5541 __ ldr(result, FieldMemOperand(scratch, | 5534 __ ldr(result, FieldMemOperand(scratch, |
5542 FixedArray::kHeaderSize - kPointerSize)); | 5535 FixedArray::kHeaderSize - kPointerSize)); |
5543 __ bind(deferred->exit()); | 5536 __ bind(deferred->exit()); |
5544 __ bind(&done); | 5537 __ bind(&done); |
5545 } | 5538 } |
5546 | 5539 |
5547 #undef __ | 5540 #undef __ |
5548 | 5541 |
5549 } // namespace internal | 5542 } // namespace internal |
5550 } // namespace v8 | 5543 } // namespace v8 |
OLD | NEW |