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