OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
11 #include "src/codegen.h" | 11 #include "src/codegen.h" |
12 #include "src/ic/handler-compiler.h" | 12 #include "src/ic/handler-compiler.h" |
13 #include "src/ic/ic.h" | 13 #include "src/ic/ic.h" |
| 14 #include "src/ic/stub-cache.h" |
14 #include "src/isolate.h" | 15 #include "src/isolate.h" |
15 #include "src/jsregexp.h" | 16 #include "src/jsregexp.h" |
16 #include "src/regexp-macro-assembler.h" | 17 #include "src/regexp-macro-assembler.h" |
17 #include "src/runtime/runtime.h" | 18 #include "src/runtime/runtime.h" |
18 | 19 |
19 namespace v8 { | 20 namespace v8 { |
20 namespace internal { | 21 namespace internal { |
21 | 22 |
22 | 23 |
23 static void InitializeArrayConstructorDescriptor( | 24 static void InitializeArrayConstructorDescriptor( |
(...skipping 4420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4444 } | 4445 } |
4445 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 4446 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
4446 __ Drop(x1); | 4447 __ Drop(x1); |
4447 // Return to IC Miss stub, continuation still on stack. | 4448 // Return to IC Miss stub, continuation still on stack. |
4448 __ Ret(); | 4449 __ Ret(); |
4449 } | 4450 } |
4450 | 4451 |
4451 | 4452 |
4452 void LoadICTrampolineStub::Generate(MacroAssembler* masm) { | 4453 void LoadICTrampolineStub::Generate(MacroAssembler* masm) { |
4453 EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); | 4454 EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); |
4454 VectorLoadStub stub(isolate(), state()); | 4455 VectorRawLoadStub stub(isolate(), state()); |
4455 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 4456 stub.GenerateForTrampoline(masm); |
4456 } | 4457 } |
4457 | 4458 |
4458 | 4459 |
4459 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) { | 4460 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) { |
4460 EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); | 4461 EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); |
4461 VectorKeyedLoadStub stub(isolate()); | 4462 VectorRawKeyedLoadStub stub(isolate()); |
4462 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 4463 stub.GenerateForTrampoline(masm); |
4463 } | 4464 } |
4464 | 4465 |
4465 | 4466 |
4466 void CallICTrampolineStub::Generate(MacroAssembler* masm) { | 4467 void CallICTrampolineStub::Generate(MacroAssembler* masm) { |
4467 EmitLoadTypeFeedbackVector(masm, x2); | 4468 EmitLoadTypeFeedbackVector(masm, x2); |
4468 CallICStub stub(isolate(), state()); | 4469 CallICStub stub(isolate(), state()); |
4469 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 4470 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
4470 } | 4471 } |
4471 | 4472 |
4472 | 4473 |
4473 void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) { | 4474 void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) { |
4474 EmitLoadTypeFeedbackVector(masm, x2); | 4475 EmitLoadTypeFeedbackVector(masm, x2); |
4475 CallIC_ArrayStub stub(isolate(), state()); | 4476 CallIC_ArrayStub stub(isolate(), state()); |
4476 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 4477 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
4477 } | 4478 } |
4478 | 4479 |
4479 | 4480 |
| 4481 void VectorRawLoadStub::Generate(MacroAssembler* masm) { |
| 4482 GenerateImpl(masm, false); |
| 4483 } |
| 4484 |
| 4485 |
| 4486 void VectorRawLoadStub::GenerateForTrampoline(MacroAssembler* masm) { |
| 4487 GenerateImpl(masm, true); |
| 4488 } |
| 4489 |
| 4490 |
| 4491 static void HandleArrayCases(MacroAssembler* masm, Register receiver, |
| 4492 Register key, Register vector, Register slot, |
| 4493 Register feedback, Register scratch1, |
| 4494 Register scratch2, Register scratch3, |
| 4495 Label* miss) { |
| 4496 // feedback initially contains the feedback array |
| 4497 Label next, next_loop, prepare_next; |
| 4498 Label load_smi_map, compare_map; |
| 4499 |
| 4500 Register receiver_map = scratch1; |
| 4501 Register array_map = scratch2; |
| 4502 |
| 4503 // Receiver might not be a heap object. |
| 4504 __ JumpIfSmi(receiver, &load_smi_map); |
| 4505 __ Ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 4506 __ Bind(&compare_map); |
| 4507 __ Ldr(array_map, |
| 4508 FieldMemOperand(feedback, FixedArray::OffsetOfElementAt(0))); |
| 4509 __ Ldr(array_map, FieldMemOperand(array_map, WeakCell::kValueOffset)); |
| 4510 __ Cmp(receiver_map, array_map); |
| 4511 __ B(ne, &next); |
| 4512 // found, now call handler. |
| 4513 __ Ldr(feedback, FieldMemOperand(feedback, FixedArray::OffsetOfElementAt(1))); |
| 4514 __ Add(feedback, feedback, Code::kHeaderSize - kHeapObjectTag); |
| 4515 __ Jump(feedback); |
| 4516 |
| 4517 Register length = scratch3; |
| 4518 __ Bind(&next); |
| 4519 __ Ldr(length, FieldMemOperand(feedback, FixedArray::kLengthOffset)); |
| 4520 __ Cmp(length, Operand(Smi::FromInt(2))); |
| 4521 Label start_polymorphic; |
| 4522 __ B(ne, &start_polymorphic); |
| 4523 __ jmp(miss); |
| 4524 |
| 4525 Register too_far = length; |
| 4526 Register pointer_reg = feedback; |
| 4527 |
| 4528 // +-----+------+------+-----+-----+ ... ----+ |
| 4529 // | map | len | wm0 | h0 | wm1 | hN | |
| 4530 // +-----+------+------+-----+-----+ ... ----+ |
| 4531 // 0 1 2 len-1 |
| 4532 // ^ ^ |
| 4533 // | | |
| 4534 // pointer_reg too_far |
| 4535 // aka feedback scratch3 |
| 4536 // also need receiver_map (aka scratch1) |
| 4537 // use array_map (scratch2) to look in the weak map values. |
| 4538 __ Bind(&start_polymorphic); |
| 4539 __ Add(too_far, feedback, |
| 4540 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); |
| 4541 __ Add(too_far, too_far, FixedArray::kHeaderSize - kHeapObjectTag); |
| 4542 __ Add(pointer_reg, feedback, |
| 4543 FixedArray::OffsetOfElementAt(2) - kHeapObjectTag); |
| 4544 |
| 4545 __ Bind(&next_loop); |
| 4546 __ Ldr(array_map, MemOperand(pointer_reg)); |
| 4547 __ Ldr(array_map, FieldMemOperand(array_map, WeakCell::kValueOffset)); |
| 4548 __ Cmp(receiver_map, array_map); |
| 4549 __ B(ne, &prepare_next); |
| 4550 __ Ldr(array_map, MemOperand(pointer_reg, kPointerSize)); |
| 4551 __ Add(array_map, array_map, Code::kHeaderSize - kHeapObjectTag); |
| 4552 __ Jump(array_map); |
| 4553 |
| 4554 __ Bind(&prepare_next); |
| 4555 __ Add(pointer_reg, pointer_reg, kPointerSize * 2); |
| 4556 __ Cmp(pointer_reg, too_far); |
| 4557 __ B(lt, &next_loop); |
| 4558 |
| 4559 // We exhausted our array of map handler pairs. |
| 4560 __ jmp(miss); |
| 4561 |
| 4562 __ Bind(&load_smi_map); |
| 4563 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
| 4564 __ jmp(&compare_map); |
| 4565 } |
| 4566 |
| 4567 |
| 4568 static void HandleMonomorphicCase(MacroAssembler* masm, Register receiver, |
| 4569 Register key, Register vector, Register slot, |
| 4570 Register weak_cell, Register scratch, |
| 4571 Label* miss) { |
| 4572 // feedback initially contains the feedback array |
| 4573 Label compare_smi_map; |
| 4574 |
| 4575 Register receiver_map = scratch; |
| 4576 |
| 4577 // Move the weak map into the weak_cell register. |
| 4578 __ Ldr(weak_cell, FieldMemOperand(weak_cell, WeakCell::kValueOffset)); |
| 4579 |
| 4580 // Receiver might not be a heap object. |
| 4581 __ JumpIfSmi(receiver, &compare_smi_map); |
| 4582 __ Ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 4583 __ Cmp(weak_cell, receiver_map); |
| 4584 __ B(ne, miss); |
| 4585 __ Add(weak_cell, vector, Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); |
| 4586 __ Ldr(weak_cell, |
| 4587 FieldMemOperand(weak_cell, FixedArray::kHeaderSize + kPointerSize)); |
| 4588 __ Add(weak_cell, weak_cell, Code::kHeaderSize - kHeapObjectTag); |
| 4589 __ Jump(weak_cell); |
| 4590 |
| 4591 // In microbenchmarks, it made sense to unroll this code so that the call to |
| 4592 // the handler is duplicated for a HeapObject receiver and a Smi receiver. |
| 4593 // TODO(mvstanton): does this hold on ARM? |
| 4594 __ Bind(&compare_smi_map); |
| 4595 __ JumpIfNotRoot(weak_cell, Heap::kHeapNumberMapRootIndex, miss); |
| 4596 __ Add(weak_cell, vector, Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); |
| 4597 __ Ldr(weak_cell, |
| 4598 FieldMemOperand(weak_cell, FixedArray::kHeaderSize + kPointerSize)); |
| 4599 __ Add(weak_cell, weak_cell, Code::kHeaderSize - kHeapObjectTag); |
| 4600 __ Jump(weak_cell); |
| 4601 } |
| 4602 |
| 4603 |
| 4604 void VectorRawLoadStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
| 4605 Register receiver = VectorLoadICDescriptor::ReceiverRegister(); // x1 |
| 4606 Register name = VectorLoadICDescriptor::NameRegister(); // x2 |
| 4607 Register vector = VectorLoadICDescriptor::VectorRegister(); // x3 |
| 4608 Register slot = VectorLoadICDescriptor::SlotRegister(); // x0 |
| 4609 Register feedback = x4; |
| 4610 Register scratch1 = x5; |
| 4611 |
| 4612 __ Add(feedback, vector, Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); |
| 4613 __ Ldr(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize)); |
| 4614 |
| 4615 // Is it a weak cell? |
| 4616 Label try_array; |
| 4617 Label not_array, smi_key, key_okay, miss; |
| 4618 __ Ldr(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset)); |
| 4619 __ JumpIfNotRoot(scratch1, Heap::kWeakCellMapRootIndex, &try_array); |
| 4620 HandleMonomorphicCase(masm, receiver, name, vector, slot, feedback, scratch1, |
| 4621 &miss); |
| 4622 __ Unreachable(); |
| 4623 |
| 4624 // Is it a fixed array? |
| 4625 __ Bind(&try_array); |
| 4626 __ JumpIfNotRoot(scratch1, Heap::kFixedArrayMapRootIndex, ¬_array); |
| 4627 HandleArrayCases(masm, receiver, name, vector, slot, feedback, scratch1, x6, |
| 4628 x7, &miss); |
| 4629 __ Unreachable(); |
| 4630 |
| 4631 __ Bind(¬_array); |
| 4632 __ JumpIfNotRoot(feedback, Heap::kmegamorphic_symbolRootIndex, &miss); |
| 4633 Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags( |
| 4634 Code::ComputeHandlerFlags(Code::LOAD_IC)); |
| 4635 masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags, |
| 4636 false, receiver, name, feedback, |
| 4637 scratch1, x6, x7); |
| 4638 |
| 4639 __ Bind(&miss); |
| 4640 LoadIC::GenerateMiss(masm); |
| 4641 } |
| 4642 |
| 4643 |
| 4644 void VectorRawKeyedLoadStub::Generate(MacroAssembler* masm) { |
| 4645 GenerateImpl(masm, false); |
| 4646 } |
| 4647 |
| 4648 |
| 4649 void VectorRawKeyedLoadStub::GenerateForTrampoline(MacroAssembler* masm) { |
| 4650 GenerateImpl(masm, true); |
| 4651 } |
| 4652 |
| 4653 |
| 4654 void VectorRawKeyedLoadStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
| 4655 Register receiver = VectorLoadICDescriptor::ReceiverRegister(); // x1 |
| 4656 Register key = VectorLoadICDescriptor::NameRegister(); // x2 |
| 4657 Register vector = VectorLoadICDescriptor::VectorRegister(); // x3 |
| 4658 Register slot = VectorLoadICDescriptor::SlotRegister(); // x0 |
| 4659 Register feedback = x4; |
| 4660 Register scratch1 = x5; |
| 4661 |
| 4662 __ Add(feedback, vector, Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); |
| 4663 __ Ldr(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize)); |
| 4664 |
| 4665 // Is it a weak cell? |
| 4666 Label try_array; |
| 4667 Label not_array, smi_key, key_okay, miss; |
| 4668 __ Ldr(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset)); |
| 4669 __ JumpIfNotRoot(scratch1, Heap::kWeakCellMapRootIndex, &try_array); |
| 4670 __ JumpIfNotSmi(key, &miss); |
| 4671 HandleMonomorphicCase(masm, receiver, key, vector, slot, feedback, scratch1, |
| 4672 &miss); |
| 4673 __ Unreachable(); |
| 4674 |
| 4675 __ Bind(&try_array); |
| 4676 // Is it a fixed array? |
| 4677 __ JumpIfNotRoot(scratch1, Heap::kFixedArrayMapRootIndex, ¬_array); |
| 4678 // We have a polymorphic element handler. |
| 4679 __ JumpIfNotSmi(key, &miss); |
| 4680 |
| 4681 Label polymorphic, try_poly_name; |
| 4682 __ Bind(&polymorphic); |
| 4683 HandleArrayCases(masm, receiver, key, vector, slot, feedback, scratch1, x6, |
| 4684 x7, &miss); |
| 4685 __ Unreachable(); |
| 4686 |
| 4687 __ Bind(¬_array); |
| 4688 // Is it generic? |
| 4689 __ JumpIfNotRoot(feedback, Heap::kmegamorphic_symbolRootIndex, |
| 4690 &try_poly_name); |
| 4691 Handle<Code> megamorphic_stub = |
| 4692 KeyedLoadIC::ChooseMegamorphicStub(masm->isolate()); |
| 4693 __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET); |
| 4694 |
| 4695 __ Bind(&try_poly_name); |
| 4696 // We might have a name in scratch, and a fixed array in the next slot. |
| 4697 __ Cmp(key, scratch1); |
| 4698 __ B(ne, &miss); |
| 4699 // If the name comparison succeeded, we know we have a fixed array with |
| 4700 // at least one map/handler pair. |
| 4701 __ Add(feedback, vector, Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); |
| 4702 __ Ldr(feedback, |
| 4703 FieldMemOperand(feedback, FixedArray::kHeaderSize + kPointerSize)); |
| 4704 __ jmp(&polymorphic); |
| 4705 |
| 4706 __ Bind(&miss); |
| 4707 KeyedLoadIC::GenerateMiss(masm); |
| 4708 } |
| 4709 |
| 4710 |
4480 // The entry hook is a "BumpSystemStackPointer" instruction (sub), followed by | 4711 // The entry hook is a "BumpSystemStackPointer" instruction (sub), followed by |
4481 // a "Push lr" instruction, followed by a call. | 4712 // a "Push lr" instruction, followed by a call. |
4482 static const unsigned int kProfileEntryHookCallSize = | 4713 static const unsigned int kProfileEntryHookCallSize = |
4483 Assembler::kCallSizeWithRelocation + (2 * kInstructionSize); | 4714 Assembler::kCallSizeWithRelocation + (2 * kInstructionSize); |
4484 | 4715 |
4485 | 4716 |
4486 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 4717 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
4487 if (masm->isolate()->function_entry_hook() != NULL) { | 4718 if (masm->isolate()->function_entry_hook() != NULL) { |
4488 ProfileEntryHookStub stub(masm->isolate()); | 4719 ProfileEntryHookStub stub(masm->isolate()); |
4489 Assembler::BlockConstPoolScope no_const_pools(masm); | 4720 Assembler::BlockConstPoolScope no_const_pools(masm); |
(...skipping 1028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5518 kStackUnwindSpace, NULL, spill_offset, | 5749 kStackUnwindSpace, NULL, spill_offset, |
5519 MemOperand(fp, 6 * kPointerSize), NULL); | 5750 MemOperand(fp, 6 * kPointerSize), NULL); |
5520 } | 5751 } |
5521 | 5752 |
5522 | 5753 |
5523 #undef __ | 5754 #undef __ |
5524 | 5755 |
5525 } } // namespace v8::internal | 5756 } } // namespace v8::internal |
5526 | 5757 |
5527 #endif // V8_TARGET_ARCH_ARM64 | 5758 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |