1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/arm64/codegen-arm64.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM64 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/simulator-arm64.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/macro-assembler.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm) 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochUnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) { 19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return nullptr; 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ------------------------------------------------------------------------- 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Platform-specific RuntimeCallHelper functions. 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->EnterFrame(StackFrame::INTERNAL); 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!masm->has_frame()); 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->set_has_frame(true); 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->LeaveFrame(StackFrame::INTERNAL); 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(masm->has_frame()); 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->set_has_frame(false); 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ------------------------------------------------------------------------- 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code generators 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCodeAgingHelper::CodeAgingHelper(Isolate* isolate) { 44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch USE(isolate); 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The sequence of instructions that is patched out for aging code is the 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // following boilerplate stack-building prologue that is found both in 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FUNCTION and OPTIMIZED_FUNCTION code: 49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PatchingAssembler patcher(isolate, young_sequence_.start(), 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch young_sequence_.length() / kInstructionSize); 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The young sequence is the frame setup code for FUNCTION code types. It is 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // generated by FullCodeGenerator::Generate. 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler::EmitFrameSetupForCodeAgePatching(&patcher); 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int length = kCodeAgeStubEntryOffset / kInstructionSize; 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(old_sequence_.length() >= kCodeAgeStubEntryOffset); 58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PatchingAssembler patcher_old(isolate, old_sequence_.start(), length); 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler::EmitCodeAgeSequence(&patcher_old, NULL); 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool CodeAgingHelper::IsOld(byte* candidate) const { 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return memcmp(candidate, old_sequence_.start(), kCodeAgeStubEntryOffset) == 0; 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Code::IsYoungSequence(Isolate* isolate, byte* sequence) { 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return MacroAssembler::IsYoungSequence(isolate, sequence); 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochCode::Age Code::GetCodeAge(Isolate* isolate, byte* sequence) { 7662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (IsYoungSequence(isolate, sequence)) return kNoAgeCodeAge; 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch byte* target = sequence + kCodeAgeStubEntryOffset; 7962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Code* stub = GetCodeFromTargetAddress(Memory::Address_at(target)); 8062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return GetAgeOfCodeAgeStub(stub); 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 8362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Code::PatchPlatformCodeAge(Isolate* isolate, byte* sequence, 8462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Code::Age age) { 85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PatchingAssembler patcher(isolate, sequence, 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kNoCodeAgeSequenceLength / kInstructionSize); 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (age == kNoAgeCodeAge) { 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler::EmitFrameSetupForCodeAgePatching(&patcher); 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 9062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Code* stub = GetCodeAgeStub(isolate, age); 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler::EmitCodeAgeSequence(&patcher, stub); 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StringCharLoadGenerator::Generate(MacroAssembler* masm, 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register string, 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index, 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* call_runtime) { 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(string.Is64Bits() && index.Is32Bits() && result.Is64Bits()); 10262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label indirect_string_loaded; 10362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&indirect_string_loaded); 10462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fetch the instance type of the receiver into result register. 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(result, FieldMemOperand(string, HeapObject::kMapOffset)); 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We need special handling for indirect strings. 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label check_sequential; 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TestAndBranchIfAllClear(result, kIsIndirectStringMask, &check_sequential); 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Dispatch on the indirect string shape: slice or cons. 11462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label cons_string, thin_string; 11562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ And(result, result, kStringRepresentationMask); 11662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Cmp(result, kConsStringTag); 11762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ B(eq, &cons_string); 11862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Cmp(result, kThinStringTag); 11962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ B(eq, &thin_string); 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Handle slices. 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(result.W(), 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UntagSmiFieldMemOperand(string, SlicedString::kOffsetOffset)); 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(string, FieldMemOperand(string, SlicedString::kParentOffset)); 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(index, index, result.W()); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&indirect_string_loaded); 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Handle thin strings. 12962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&thin_string); 13062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Ldr(string, FieldMemOperand(string, ThinString::kActualOffset)); 13162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ B(&indirect_string_loaded); 13262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Handle cons strings. 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check whether the right hand side is the empty string (i.e. if 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // this is really a flat string in a cons string). If that is not 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the case we would rather go to the runtime system now to flatten 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the string. 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&cons_string); 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(result, FieldMemOperand(string, ConsString::kSecondOffset)); 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotRoot(result, Heap::kempty_stringRootIndex, call_runtime); 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the first of the two strings and load its instance type. 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(string, FieldMemOperand(string, ConsString::kFirstOffset)); 14362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ B(&indirect_string_loaded); 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Distinguish sequential and external strings. Only these two string 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // representations can reach here (slices and flat cons strings have been 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // reduced to the underlying sequential or external string). 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label external_string, check_encoding; 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&check_sequential); 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSeqStringTag == 0); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TestAndBranchIfAnySet(result, kStringRepresentationMask, &external_string); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prepare sequential strings 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(string, string, SeqTwoByteString::kHeaderSize - kHeapObjectTag); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&check_encoding); 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Handle external strings. 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&external_string); 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assert that we do not have a cons or slice (indirect strings) here. 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Sequential strings have already been ruled out. 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Tst(result, kIsIndirectStringMask); 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(eq, kExternalStringExpectedButNotFound); 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Rule out short external strings. 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kShortExternalStringTag != 0); 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TestAndBranchIfAnySet can emit Tbnz. Do not use it because call_runtime 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // can be bound far away in deferred code. 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Tst(result, kShortExternalStringMask); 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(ne, call_runtime); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(string, FieldMemOperand(string, ExternalString::kResourceDataOffset)); 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label one_byte, done; 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&check_encoding); 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kTwoByteStringTag == 0); 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TestAndBranchIfAnySet(result, kStringEncodingMask, &one_byte); 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Two-byte string. 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrh(result, MemOperand(string, index, SXTW, 1)); 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&one_byte); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // One-byte string. 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(result, MemOperand(string, index, SXTW)); 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_ARM64 193