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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.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/codegen.h" | 10 #include "src/codegen.h" |
11 #include "src/debug/debug.h" | 11 #include "src/debug/debug.h" |
12 #include "src/full-codegen/full-codegen.h" | 12 #include "src/full-codegen/full-codegen.h" |
13 #include "src/ic/ic.h" | 13 #include "src/ic/ic.h" |
14 #include "src/parsing/parser.h" | 14 #include "src/parsing/parser.h" |
15 | 15 |
16 #include "src/arm64/code-stubs-arm64.h" | 16 #include "src/arm64/code-stubs-arm64.h" |
17 #include "src/arm64/frames-arm64.h" | 17 #include "src/arm64/frames-arm64.h" |
18 #include "src/arm64/macro-assembler-arm64.h" | 18 #include "src/arm64/macro-assembler-arm64.h" |
19 | 19 |
20 namespace v8 { | 20 namespace v8 { |
21 namespace internal { | 21 namespace internal { |
22 | 22 |
23 #define __ ACCESS_MASM(masm_) | 23 #define __ ACCESS_MASM(masm()) |
24 | 24 |
25 class JumpPatchSite BASE_EMBEDDED { | 25 class JumpPatchSite BASE_EMBEDDED { |
26 public: | 26 public: |
27 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm), reg_(NoReg) { | 27 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm), reg_(NoReg) { |
28 #ifdef DEBUG | 28 #ifdef DEBUG |
29 info_emitted_ = false; | 29 info_emitted_ = false; |
30 #endif | 30 #endif |
31 } | 31 } |
32 | 32 |
33 ~JumpPatchSite() { | 33 ~JumpPatchSite() { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 | 69 |
70 void EmitPatchInfo() { | 70 void EmitPatchInfo() { |
71 Assembler::BlockPoolsScope scope(masm_); | 71 Assembler::BlockPoolsScope scope(masm_); |
72 InlineSmiCheckInfo::Emit(masm_, reg_, &patch_site_); | 72 InlineSmiCheckInfo::Emit(masm_, reg_, &patch_site_); |
73 #ifdef DEBUG | 73 #ifdef DEBUG |
74 info_emitted_ = true; | 74 info_emitted_ = true; |
75 #endif | 75 #endif |
76 } | 76 } |
77 | 77 |
78 private: | 78 private: |
| 79 MacroAssembler* masm() { return masm_; } |
79 MacroAssembler* masm_; | 80 MacroAssembler* masm_; |
80 Label patch_site_; | 81 Label patch_site_; |
81 Register reg_; | 82 Register reg_; |
82 #ifdef DEBUG | 83 #ifdef DEBUG |
83 bool info_emitted_; | 84 bool info_emitted_; |
84 #endif | 85 #endif |
85 }; | 86 }; |
86 | 87 |
87 | 88 |
88 // Generate code for a JS function. On entry to the function the receiver | 89 // Generate code for a JS function. On entry to the function the receiver |
(...skipping 4254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4343 __ Bind(&continuation); | 4344 __ Bind(&continuation); |
4344 // When we arrive here, the stack top is the resume mode and | 4345 // When we arrive here, the stack top is the resume mode and |
4345 // result_register() holds the input value (the argument given to the | 4346 // result_register() holds the input value (the argument given to the |
4346 // respective resume operation). | 4347 // respective resume operation). |
4347 __ RecordGeneratorContinuation(); | 4348 __ RecordGeneratorContinuation(); |
4348 __ Pop(x1); | 4349 __ Pop(x1); |
4349 __ Cmp(x1, Smi::FromInt(JSGeneratorObject::RETURN)); | 4350 __ Cmp(x1, Smi::FromInt(JSGeneratorObject::RETURN)); |
4350 __ B(ne, &resume); | 4351 __ B(ne, &resume); |
4351 __ Push(result_register()); | 4352 __ Push(result_register()); |
4352 EmitCreateIteratorResult(true); | 4353 EmitCreateIteratorResult(true); |
4353 EmitUnwindBeforeReturn(); | 4354 EmitUnwindAndReturn(); |
4354 EmitReturnSequence(); | |
4355 | 4355 |
4356 __ Bind(&suspend); | 4356 __ Bind(&suspend); |
4357 VisitForAccumulatorValue(expr->generator_object()); | 4357 VisitForAccumulatorValue(expr->generator_object()); |
4358 DCHECK((continuation.pos() > 0) && Smi::IsValid(continuation.pos())); | 4358 DCHECK((continuation.pos() > 0) && Smi::IsValid(continuation.pos())); |
4359 __ Mov(x1, Smi::FromInt(continuation.pos())); | 4359 __ Mov(x1, Smi::FromInt(continuation.pos())); |
4360 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); | 4360 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); |
4361 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); | 4361 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); |
4362 __ Mov(x1, cp); | 4362 __ Mov(x1, cp); |
4363 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, | 4363 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, |
4364 kLRHasBeenSaved, kDontSaveFPRegs); | 4364 kLRHasBeenSaved, kDontSaveFPRegs); |
4365 __ Add(x1, fp, StandardFrameConstants::kExpressionsOffset); | 4365 __ Add(x1, fp, StandardFrameConstants::kExpressionsOffset); |
4366 __ Cmp(__ StackPointer(), x1); | 4366 __ Cmp(__ StackPointer(), x1); |
4367 __ B(eq, &post_runtime); | 4367 __ B(eq, &post_runtime); |
4368 __ Push(x0); // generator object | 4368 __ Push(x0); // generator object |
4369 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 4369 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
4370 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4370 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
4371 __ Bind(&post_runtime); | 4371 __ Bind(&post_runtime); |
4372 __ Pop(result_register()); | 4372 __ Pop(result_register()); |
4373 EmitReturnSequence(); | 4373 EmitReturnSequence(); |
4374 | 4374 |
4375 __ Bind(&resume); | 4375 __ Bind(&resume); |
4376 context()->Plug(result_register()); | 4376 context()->Plug(result_register()); |
4377 break; | 4377 break; |
4378 } | 4378 } |
4379 | 4379 |
4380 case Yield::kFinal: { | 4380 case Yield::kFinal: { |
4381 // Pop value from top-of-stack slot, box result into result register. | 4381 // Pop value from top-of-stack slot, box result into result register. |
4382 EmitCreateIteratorResult(true); | 4382 EmitCreateIteratorResult(true); |
4383 EmitUnwindBeforeReturn(); | 4383 EmitUnwindAndReturn(); |
4384 EmitReturnSequence(); | |
4385 break; | 4384 break; |
4386 } | 4385 } |
4387 | 4386 |
4388 case Yield::kDelegating: { | 4387 case Yield::kDelegating: { |
4389 VisitForStackValue(expr->generator_object()); | 4388 VisitForStackValue(expr->generator_object()); |
4390 | 4389 |
4391 // Initial stack layout is as follows: | 4390 // Initial stack layout is as follows: |
4392 // [sp + 1 * kPointerSize] iter | 4391 // [sp + 1 * kPointerSize] iter |
4393 // [sp + 0 * kPointerSize] g | 4392 // [sp + 0 * kPointerSize] g |
4394 | 4393 |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4686 DCHECK(closure_scope->is_function_scope()); | 4685 DCHECK(closure_scope->is_function_scope()); |
4687 __ Ldr(x10, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 4686 __ Ldr(x10, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
4688 } | 4687 } |
4689 __ Push(x10); | 4688 __ Push(x10); |
4690 } | 4689 } |
4691 | 4690 |
4692 | 4691 |
4693 void FullCodeGenerator::EnterFinallyBlock() { | 4692 void FullCodeGenerator::EnterFinallyBlock() { |
4694 ASM_LOCATION("FullCodeGenerator::EnterFinallyBlock"); | 4693 ASM_LOCATION("FullCodeGenerator::EnterFinallyBlock"); |
4695 DCHECK(!result_register().is(x10)); | 4694 DCHECK(!result_register().is(x10)); |
4696 // Preserve the result register while executing finally block. | |
4697 // Also cook the return address in lr to the stack (smi encoded Code* delta). | |
4698 __ Sub(x10, lr, Operand(masm_->CodeObject())); | |
4699 __ SmiTag(x10); | |
4700 __ Push(result_register(), x10); | |
4701 | |
4702 // Store pending message while executing finally block. | 4695 // Store pending message while executing finally block. |
4703 ExternalReference pending_message_obj = | 4696 ExternalReference pending_message_obj = |
4704 ExternalReference::address_of_pending_message_obj(isolate()); | 4697 ExternalReference::address_of_pending_message_obj(isolate()); |
4705 __ Mov(x10, pending_message_obj); | 4698 __ Mov(x10, pending_message_obj); |
4706 __ Ldr(x10, MemOperand(x10)); | 4699 __ Ldr(x10, MemOperand(x10)); |
4707 __ Push(x10); | 4700 __ Push(x10); |
4708 | 4701 |
4709 ClearPendingMessage(); | 4702 ClearPendingMessage(); |
4710 } | 4703 } |
4711 | 4704 |
4712 | 4705 |
4713 void FullCodeGenerator::ExitFinallyBlock() { | 4706 void FullCodeGenerator::ExitFinallyBlock() { |
4714 ASM_LOCATION("FullCodeGenerator::ExitFinallyBlock"); | 4707 ASM_LOCATION("FullCodeGenerator::ExitFinallyBlock"); |
4715 DCHECK(!result_register().is(x10)); | 4708 DCHECK(!result_register().is(x10)); |
4716 | 4709 |
4717 // Restore pending message from stack. | 4710 // Restore pending message from stack. |
4718 __ Pop(x10); | 4711 __ Pop(x10); |
4719 ExternalReference pending_message_obj = | 4712 ExternalReference pending_message_obj = |
4720 ExternalReference::address_of_pending_message_obj(isolate()); | 4713 ExternalReference::address_of_pending_message_obj(isolate()); |
4721 __ Mov(x13, pending_message_obj); | 4714 __ Mov(x13, pending_message_obj); |
4722 __ Str(x10, MemOperand(x13)); | 4715 __ Str(x10, MemOperand(x13)); |
4723 | |
4724 // Restore result register and cooked return address from the stack. | |
4725 __ Pop(x10, result_register()); | |
4726 | |
4727 // Uncook the return address (see EnterFinallyBlock). | |
4728 __ SmiUntag(x10); | |
4729 __ Add(x11, x10, Operand(masm_->CodeObject())); | |
4730 __ Br(x11); | |
4731 } | 4716 } |
4732 | 4717 |
4733 | 4718 |
4734 void FullCodeGenerator::ClearPendingMessage() { | 4719 void FullCodeGenerator::ClearPendingMessage() { |
4735 DCHECK(!result_register().is(x10)); | 4720 DCHECK(!result_register().is(x10)); |
4736 ExternalReference pending_message_obj = | 4721 ExternalReference pending_message_obj = |
4737 ExternalReference::address_of_pending_message_obj(isolate()); | 4722 ExternalReference::address_of_pending_message_obj(isolate()); |
4738 __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); | 4723 __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); |
4739 __ Mov(x13, pending_message_obj); | 4724 __ Mov(x13, pending_message_obj); |
4740 __ Str(x10, MemOperand(x13)); | 4725 __ Str(x10, MemOperand(x13)); |
4741 } | 4726 } |
4742 | 4727 |
4743 | 4728 |
4744 void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) { | 4729 void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) { |
4745 DCHECK(!slot.IsInvalid()); | 4730 DCHECK(!slot.IsInvalid()); |
4746 __ Mov(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot)); | 4731 __ Mov(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot)); |
4747 } | 4732 } |
4748 | 4733 |
| 4734 void FullCodeGenerator::DeferredCommands::EmitCommands() { |
| 4735 __ Pop(result_register(), x1); // Restore the accumulator and get the token. |
| 4736 for (DeferredCommand cmd : commands_) { |
| 4737 Label skip; |
| 4738 __ Cmp(x1, Operand(Smi::FromInt(cmd.token))); |
| 4739 __ B(ne, &skip); |
| 4740 switch (cmd.command) { |
| 4741 case kReturn: |
| 4742 codegen_->EmitUnwindAndReturn(); |
| 4743 break; |
| 4744 case kThrow: |
| 4745 __ Push(result_register()); |
| 4746 __ CallRuntime(Runtime::kReThrow); |
| 4747 break; |
| 4748 case kContinue: |
| 4749 codegen_->EmitContinue(cmd.target); |
| 4750 break; |
| 4751 case kBreak: |
| 4752 codegen_->EmitBreak(cmd.target); |
| 4753 break; |
| 4754 } |
| 4755 __ bind(&skip); |
| 4756 } |
| 4757 } |
4749 | 4758 |
4750 #undef __ | 4759 #undef __ |
4751 | 4760 |
4752 | 4761 |
4753 void BackEdgeTable::PatchAt(Code* unoptimized_code, | 4762 void BackEdgeTable::PatchAt(Code* unoptimized_code, |
4754 Address pc, | 4763 Address pc, |
4755 BackEdgeState target_state, | 4764 BackEdgeState target_state, |
4756 Code* replacement_code) { | 4765 Code* replacement_code) { |
4757 // Turn the jump into a nop. | 4766 // Turn the jump into a nop. |
4758 Address branch_address = pc - 3 * kInstructionSize; | 4767 Address branch_address = pc - 3 * kInstructionSize; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4835 } | 4844 } |
4836 | 4845 |
4837 return INTERRUPT; | 4846 return INTERRUPT; |
4838 } | 4847 } |
4839 | 4848 |
4840 | 4849 |
4841 } // namespace internal | 4850 } // namespace internal |
4842 } // namespace v8 | 4851 } // namespace v8 |
4843 | 4852 |
4844 #endif // V8_TARGET_ARCH_ARM64 | 4853 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |