1a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org// Copyright 2012 the V8 project authors. All rights reserved. 2a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be 3a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org// found in the LICENSE file. 4a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 5a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#include "src/v8.h" 6a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 7a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#if V8_TARGET_ARCH_ARM 8a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 9a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#include "src/codegen.h" 10a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#include "src/ic/stub-cache.h" 11a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 12a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgnamespace v8 { 13a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgnamespace internal { 14a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 15a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#define __ ACCESS_MASM(masm) 16a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 17a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 18a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgstatic void ProbeTable(Isolate* isolate, MacroAssembler* masm, 19e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org Code::Flags flags, bool leave_frame, 20e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org StubCache::Table table, Register receiver, Register name, 21a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Number of the cache entry, not scaled. 22a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org Register offset, Register scratch, Register scratch2, 23a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org Register offset_scratch) { 24a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); 25a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); 26a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); 27a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 28a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address()); 29a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address()); 30a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org uint32_t map_off_addr = reinterpret_cast<uint32_t>(map_offset.address()); 31a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 32a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Check the relative positions of the address fields. 33a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(value_off_addr > key_off_addr); 34a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK((value_off_addr - key_off_addr) % 4 == 0); 35a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK((value_off_addr - key_off_addr) < (256 * 4)); 36a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(map_off_addr > key_off_addr); 37a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK((map_off_addr - key_off_addr) % 4 == 0); 38a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK((map_off_addr - key_off_addr) < (256 * 4)); 39a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 40a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org Label miss; 41a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org Register base_addr = scratch; 42a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org scratch = no_reg; 43a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 44a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Multiply by 3 because there are 3 fields per entry (name, code, map). 45a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ add(offset_scratch, offset, Operand(offset, LSL, 1)); 46a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 47a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Calculate the base address of the entry. 48a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ mov(base_addr, Operand(key_offset)); 49a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ add(base_addr, base_addr, Operand(offset_scratch, LSL, kPointerSizeLog2)); 50a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 51a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Check that the key in the entry matches the name. 52a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ ldr(ip, MemOperand(base_addr, 0)); 53a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ cmp(name, ip); 54a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ b(ne, &miss); 55a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 56a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Check the map matches. 57a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ ldr(ip, MemOperand(base_addr, map_off_addr - key_off_addr)); 58a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ ldr(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); 59a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ cmp(ip, scratch2); 60a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ b(ne, &miss); 61a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 62a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Get the code entry from the cache. 63a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org Register code = scratch2; 64a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org scratch2 = no_reg; 65a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ ldr(code, MemOperand(base_addr, value_off_addr - key_off_addr)); 66a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 67a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Check that the flags match what we're looking for. 68a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org Register flags_reg = base_addr; 69a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org base_addr = no_reg; 70a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ ldr(flags_reg, FieldMemOperand(code, Code::kFlagsOffset)); 71a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // It's a nice optimization if this constant is encodable in the bic insn. 72a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 73a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org uint32_t mask = Code::kFlagsNotUsedInLookup; 74a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(__ ImmediateFitsAddrMode1Instruction(mask)); 75a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ bic(flags_reg, flags_reg, Operand(mask)); 76a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ cmp(flags_reg, Operand(flags)); 77a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ b(ne, &miss); 78a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 79a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#ifdef DEBUG 80a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { 81a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ jmp(&miss); 82a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { 83a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ jmp(&miss); 84a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org } 85a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#endif 86a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 87e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org if (leave_frame) __ LeaveFrame(StackFrame::INTERNAL); 88e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org 89a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Jump to the first instruction in the code stub. 90a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ add(pc, code, Operand(Code::kHeaderSize - kHeapObjectTag)); 91a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 92a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Miss: fall through. 93a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ bind(&miss); 94a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org} 95a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 96a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 97a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgvoid StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags, 98e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org bool leave_frame, Register receiver, 99e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org Register name, Register scratch, Register extra, 100e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org Register extra2, Register extra3) { 101a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org Isolate* isolate = masm->isolate(); 102a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org Label miss; 103a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 104a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Make sure that code is valid. The multiplying code relies on the 105a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // entry size being 12. 106a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(sizeof(Entry) == 12); 107a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 108a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Make sure the flags does not name a specific type. 109a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(Code::ExtractTypeFromFlags(flags) == 0); 110a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 111a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Make sure that there are no register conflicts. 112a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(!scratch.is(receiver)); 113a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(!scratch.is(name)); 114a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(!extra.is(receiver)); 115a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(!extra.is(name)); 116a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(!extra.is(scratch)); 117a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(!extra2.is(receiver)); 118a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(!extra2.is(name)); 119a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(!extra2.is(scratch)); 120a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(!extra2.is(extra)); 121a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 122a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Check scratch, extra and extra2 registers are valid. 123a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(!scratch.is(no_reg)); 124a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(!extra.is(no_reg)); 125a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(!extra2.is(no_reg)); 126a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org DCHECK(!extra3.is(no_reg)); 127a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 128a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org Counters* counters = masm->isolate()->counters(); 129a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, extra2, 130a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org extra3); 131a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 132a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Check that the receiver isn't a smi. 133a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ JumpIfSmi(receiver, &miss); 134a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 135a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Get the map of the receiver and compute the hash. 136a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ ldr(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); 137a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset)); 138a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ add(scratch, scratch, Operand(ip)); 139a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org uint32_t mask = kPrimaryTableSize - 1; 140a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // We shift out the last two bits because they are not part of the hash and 141a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // they are always 01 for maps. 142a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ mov(scratch, Operand(scratch, LSR, kCacheIndexShift)); 143a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Mask down the eor argument to the minimum to keep the immediate 144a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // ARM-encodable. 145a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ eor(scratch, scratch, Operand((flags >> kCacheIndexShift) & mask)); 146a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Prefer and_ to ubfx here because ubfx takes 2 cycles. 147a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ and_(scratch, scratch, Operand(mask)); 148a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 149a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Probe the primary table. 150e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org ProbeTable(isolate, masm, flags, leave_frame, kPrimary, receiver, name, 151e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org scratch, extra, extra2, extra3); 152a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 153a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Primary miss: Compute hash for secondary probe. 154a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ sub(scratch, scratch, Operand(name, LSR, kCacheIndexShift)); 155a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org uint32_t mask2 = kSecondaryTableSize - 1; 156a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ add(scratch, scratch, Operand((flags >> kCacheIndexShift) & mask2)); 157a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ and_(scratch, scratch, Operand(mask2)); 158a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 159a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Probe the secondary table. 160e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org ProbeTable(isolate, masm, flags, leave_frame, kSecondary, receiver, name, 161e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org scratch, extra, extra2, extra3); 162a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 163a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // Cache miss: Fall-through and let caller handle the miss by 164a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org // entering the runtime system. 165a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ bind(&miss); 166a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, extra2, 167a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org extra3); 168a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org} 169a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 170a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 171a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#undef __ 172a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org} 173a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org} // namespace v8::internal 174a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org 175a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#endif // V8_TARGET_ARCH_ARM 176