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 bool is_polymorphic, Label* miss) { |
| 4496 // feedback initially contains the feedback array |
| 4497 Label next_loop, prepare_next; |
| 4498 Label load_smi_map, compare_map; |
| 4499 Label start_polymorphic; |
| 4500 |
| 4501 Register receiver_map = scratch1; |
| 4502 Register cached_map = scratch2; |
| 4503 |
| 4504 // Receiver might not be a heap object. |
| 4505 __ JumpIfSmi(receiver, &load_smi_map); |
| 4506 __ Ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 4507 __ Bind(&compare_map); |
| 4508 __ Ldr(cached_map, |
| 4509 FieldMemOperand(feedback, FixedArray::OffsetOfElementAt(0))); |
| 4510 __ Ldr(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset)); |
| 4511 __ Cmp(receiver_map, cached_map); |
| 4512 __ B(ne, &start_polymorphic); |
| 4513 // found, now call handler. |
| 4514 Register handler = feedback; |
| 4515 __ Ldr(handler, FieldMemOperand(feedback, FixedArray::OffsetOfElementAt(1))); |
| 4516 __ Add(handler, handler, Code::kHeaderSize - kHeapObjectTag); |
| 4517 __ Jump(feedback); |
| 4518 |
| 4519 Register length = scratch3; |
| 4520 __ Bind(&start_polymorphic); |
| 4521 __ Ldr(length, FieldMemOperand(feedback, FixedArray::kLengthOffset)); |
| 4522 if (!is_polymorphic) { |
| 4523 __ Cmp(length, Operand(Smi::FromInt(2))); |
| 4524 __ B(eq, miss); |
| 4525 } |
| 4526 |
| 4527 Register too_far = length; |
| 4528 Register pointer_reg = feedback; |
| 4529 |
| 4530 // +-----+------+------+-----+-----+ ... ----+ |
| 4531 // | map | len | wm0 | h0 | wm1 | hN | |
| 4532 // +-----+------+------+-----+-----+ ... ----+ |
| 4533 // 0 1 2 len-1 |
| 4534 // ^ ^ |
| 4535 // | | |
| 4536 // pointer_reg too_far |
| 4537 // aka feedback scratch3 |
| 4538 // also need receiver_map (aka scratch1) |
| 4539 // use cached_map (scratch2) to look in the weak map values. |
| 4540 __ Add(too_far, feedback, |
| 4541 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); |
| 4542 __ Add(too_far, too_far, FixedArray::kHeaderSize - kHeapObjectTag); |
| 4543 __ Add(pointer_reg, feedback, |
| 4544 FixedArray::OffsetOfElementAt(2) - kHeapObjectTag); |
| 4545 |
| 4546 __ Bind(&next_loop); |
| 4547 __ Ldr(cached_map, MemOperand(pointer_reg)); |
| 4548 __ Ldr(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset)); |
| 4549 __ Cmp(receiver_map, cached_map); |
| 4550 __ B(ne, &prepare_next); |
| 4551 __ Ldr(handler, MemOperand(pointer_reg, kPointerSize)); |
| 4552 __ Add(handler, handler, Code::kHeaderSize - kHeapObjectTag); |
| 4553 __ Jump(handler); |
| 4554 |
| 4555 __ Bind(&prepare_next); |
| 4556 __ Add(pointer_reg, pointer_reg, kPointerSize * 2); |
| 4557 __ Cmp(pointer_reg, too_far); |
| 4558 __ B(lt, &next_loop); |
| 4559 |
| 4560 // We exhausted our array of map handler pairs. |
| 4561 __ jmp(miss); |
| 4562 |
| 4563 __ Bind(&load_smi_map); |
| 4564 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
| 4565 __ jmp(&compare_map); |
| 4566 } |
| 4567 |
| 4568 |
| 4569 static void HandleMonomorphicCase(MacroAssembler* masm, Register receiver, |
| 4570 Register key, Register vector, Register slot, |
| 4571 Register weak_cell, Register scratch, |
| 4572 Label* miss) { |
| 4573 // feedback initially contains the feedback array |
| 4574 Label compare_smi_map; |
| 4575 Register receiver_map = scratch; |
| 4576 Register cached_map = weak_cell; |
| 4577 |
| 4578 // Move the weak map into the weak_cell register. |
| 4579 __ Ldr(cached_map, FieldMemOperand(weak_cell, WeakCell::kValueOffset)); |
| 4580 |
| 4581 // Receiver might not be a heap object. |
| 4582 __ JumpIfSmi(receiver, &compare_smi_map); |
| 4583 __ Ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 4584 __ Cmp(cached_map, receiver_map); |
| 4585 __ B(ne, miss); |
| 4586 |
| 4587 Register handler = weak_cell; |
| 4588 __ Add(handler, vector, Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); |
| 4589 __ Ldr(handler, |
| 4590 FieldMemOperand(handler, FixedArray::kHeaderSize + kPointerSize)); |
| 4591 __ Add(handler, handler, Code::kHeaderSize - kHeapObjectTag); |
| 4592 __ Jump(weak_cell); |
| 4593 |
| 4594 // In microbenchmarks, it made sense to unroll this code so that the call to |
| 4595 // the handler is duplicated for a HeapObject receiver and a Smi receiver. |
| 4596 // TODO(mvstanton): does this hold on ARM? |
| 4597 __ Bind(&compare_smi_map); |
| 4598 __ JumpIfNotRoot(weak_cell, Heap::kHeapNumberMapRootIndex, miss); |
| 4599 __ Add(handler, vector, Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); |
| 4600 __ Ldr(handler, |
| 4601 FieldMemOperand(handler, FixedArray::kHeaderSize + kPointerSize)); |
| 4602 __ Add(handler, handler, Code::kHeaderSize - kHeapObjectTag); |
| 4603 __ Jump(handler); |
| 4604 } |
| 4605 |
| 4606 |
| 4607 void VectorRawLoadStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
| 4608 Register receiver = VectorLoadICDescriptor::ReceiverRegister(); // x1 |
| 4609 Register name = VectorLoadICDescriptor::NameRegister(); // x2 |
| 4610 Register vector = VectorLoadICDescriptor::VectorRegister(); // x3 |
| 4611 Register slot = VectorLoadICDescriptor::SlotRegister(); // x0 |
| 4612 Register feedback = x4; |
| 4613 Register scratch1 = x5; |
| 4614 |
| 4615 __ Add(feedback, vector, Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); |
| 4616 __ Ldr(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize)); |
| 4617 |
| 4618 // Is it a weak cell? |
| 4619 Label try_array; |
| 4620 Label not_array, smi_key, key_okay, miss; |
| 4621 __ Ldr(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset)); |
| 4622 __ JumpIfNotRoot(scratch1, Heap::kWeakCellMapRootIndex, &try_array); |
| 4623 HandleMonomorphicCase(masm, receiver, name, vector, slot, feedback, scratch1, |
| 4624 &miss); |
| 4625 |
| 4626 // Is it a fixed array? |
| 4627 __ Bind(&try_array); |
| 4628 __ JumpIfNotRoot(scratch1, Heap::kFixedArrayMapRootIndex, ¬_array); |
| 4629 HandleArrayCases(masm, receiver, name, vector, slot, feedback, scratch1, x6, |
| 4630 x7, true, &miss); |
| 4631 |
| 4632 __ Bind(¬_array); |
| 4633 __ JumpIfNotRoot(feedback, Heap::kmegamorphic_symbolRootIndex, &miss); |
| 4634 Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags( |
| 4635 Code::ComputeHandlerFlags(Code::LOAD_IC)); |
| 4636 masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags, |
| 4637 false, receiver, name, feedback, |
| 4638 scratch1, x6, x7); |
| 4639 |
| 4640 __ Bind(&miss); |
| 4641 LoadIC::GenerateMiss(masm); |
| 4642 } |
| 4643 |
| 4644 |
| 4645 void VectorRawKeyedLoadStub::Generate(MacroAssembler* masm) { |
| 4646 GenerateImpl(masm, false); |
| 4647 } |
| 4648 |
| 4649 |
| 4650 void VectorRawKeyedLoadStub::GenerateForTrampoline(MacroAssembler* masm) { |
| 4651 GenerateImpl(masm, true); |
| 4652 } |
| 4653 |
| 4654 |
| 4655 void VectorRawKeyedLoadStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
| 4656 Register receiver = VectorLoadICDescriptor::ReceiverRegister(); // x1 |
| 4657 Register key = VectorLoadICDescriptor::NameRegister(); // x2 |
| 4658 Register vector = VectorLoadICDescriptor::VectorRegister(); // x3 |
| 4659 Register slot = VectorLoadICDescriptor::SlotRegister(); // x0 |
| 4660 Register feedback = x4; |
| 4661 Register scratch1 = x5; |
| 4662 |
| 4663 __ Add(feedback, vector, Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); |
| 4664 __ Ldr(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize)); |
| 4665 |
| 4666 // Is it a weak cell? |
| 4667 Label try_array; |
| 4668 Label not_array, smi_key, key_okay, miss; |
| 4669 __ Ldr(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset)); |
| 4670 __ JumpIfNotRoot(scratch1, Heap::kWeakCellMapRootIndex, &try_array); |
| 4671 __ JumpIfNotSmi(key, &miss); |
| 4672 HandleMonomorphicCase(masm, receiver, key, vector, slot, feedback, scratch1, |
| 4673 &miss); |
| 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, true, &miss); |
| 4685 |
| 4686 __ Bind(¬_array); |
| 4687 // Is it generic? |
| 4688 __ JumpIfNotRoot(feedback, Heap::kmegamorphic_symbolRootIndex, |
| 4689 &try_poly_name); |
| 4690 Handle<Code> megamorphic_stub = |
| 4691 KeyedLoadIC::ChooseMegamorphicStub(masm->isolate()); |
| 4692 __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET); |
| 4693 |
| 4694 __ Bind(&try_poly_name); |
| 4695 // We might have a name in feedback, and a fixed array in the next slot. |
| 4696 __ Cmp(key, feedback); |
| 4697 __ B(ne, &miss); |
| 4698 // If the name comparison succeeded, we know we have a fixed array with |
| 4699 // at least one map/handler pair. |
| 4700 __ Add(feedback, vector, Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); |
| 4701 __ Ldr(feedback, |
| 4702 FieldMemOperand(feedback, FixedArray::kHeaderSize + kPointerSize)); |
| 4703 HandleArrayCases(masm, receiver, key, vector, slot, feedback, scratch1, x6, |
| 4704 x7, false, &miss); |
| 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 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5514 kStackUnwindSpace, NULL, spill_offset, | 5745 kStackUnwindSpace, NULL, spill_offset, |
5515 MemOperand(fp, 6 * kPointerSize), NULL); | 5746 MemOperand(fp, 6 * kPointerSize), NULL); |
5516 } | 5747 } |
5517 | 5748 |
5518 | 5749 |
5519 #undef __ | 5750 #undef __ |
5520 | 5751 |
5521 } } // namespace v8::internal | 5752 } } // namespace v8::internal |
5522 | 5753 |
5523 #endif // V8_TARGET_ARCH_ARM64 | 5754 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |