16474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org// Copyright 2012 the V8 project authors. All rights reserved. 26474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be 36474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org// found in the LICENSE file. 46474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 56474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#include "src/v8.h" 66474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 76474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#if V8_TARGET_ARCH_MIPS 86474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 96474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#include "src/codegen.h" 106474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#include "src/ic/stub-cache.h" 116474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 126474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgnamespace v8 { 136474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgnamespace internal { 146474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 156474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#define __ ACCESS_MASM(masm) 166474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 176474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 186474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@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, 216474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Number of the cache entry, not scaled. 226474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org Register offset, Register scratch, Register scratch2, 236474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org Register offset_scratch) { 246474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); 256474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); 266474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); 276474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 286474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address()); 296474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address()); 306474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org uint32_t map_off_addr = reinterpret_cast<uint32_t>(map_offset.address()); 316474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 326474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Check the relative positions of the address fields. 336474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(value_off_addr > key_off_addr); 346474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK((value_off_addr - key_off_addr) % 4 == 0); 356474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK((value_off_addr - key_off_addr) < (256 * 4)); 366474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(map_off_addr > key_off_addr); 376474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK((map_off_addr - key_off_addr) % 4 == 0); 386474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK((map_off_addr - key_off_addr) < (256 * 4)); 396474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 406474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org Label miss; 416474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org Register base_addr = scratch; 426474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org scratch = no_reg; 436474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 446474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Multiply by 3 because there are 3 fields per entry (name, code, map). 456474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ sll(offset_scratch, offset, 1); 466474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ Addu(offset_scratch, offset_scratch, offset); 476474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 486474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Calculate the base address of the entry. 496474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ li(base_addr, Operand(key_offset)); 506474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ sll(at, offset_scratch, kPointerSizeLog2); 516474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ Addu(base_addr, base_addr, at); 526474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 536474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Check that the key in the entry matches the name. 546474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ lw(at, MemOperand(base_addr, 0)); 556474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ Branch(&miss, ne, name, Operand(at)); 566474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 576474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Check the map matches. 586474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ lw(at, MemOperand(base_addr, map_off_addr - key_off_addr)); 596474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ lw(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); 606474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ Branch(&miss, ne, at, Operand(scratch2)); 616474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 626474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Get the code entry from the cache. 636474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org Register code = scratch2; 646474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org scratch2 = no_reg; 656474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ lw(code, MemOperand(base_addr, value_off_addr - key_off_addr)); 666474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 676474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Check that the flags match what we're looking for. 686474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org Register flags_reg = base_addr; 696474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org base_addr = no_reg; 706474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ lw(flags_reg, FieldMemOperand(code, Code::kFlagsOffset)); 716474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ And(flags_reg, flags_reg, Operand(~Code::kFlagsNotUsedInLookup)); 726474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ Branch(&miss, ne, flags_reg, Operand(flags)); 736474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 746474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#ifdef DEBUG 756474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { 766474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ jmp(&miss); 776474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { 786474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ jmp(&miss); 796474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org } 806474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#endif 816474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 82e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org if (leave_frame) __ LeaveFrame(StackFrame::INTERNAL); 83e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org 846474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Jump to the first instruction in the code stub. 856474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ Addu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag)); 866474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ Jump(at); 876474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 886474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Miss: fall through. 896474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ bind(&miss); 906474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org} 916474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 926474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 936474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.orgvoid StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags, 94e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org bool leave_frame, Register receiver, 95e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org Register name, Register scratch, Register extra, 96e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org Register extra2, Register extra3) { 976474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org Isolate* isolate = masm->isolate(); 986474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org Label miss; 996474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1006474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Make sure that code is valid. The multiplying code relies on the 1016474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // entry size being 12. 1026474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(sizeof(Entry) == 12); 1036474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1046474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Make sure the flags does not name a specific type. 1056474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(Code::ExtractTypeFromFlags(flags) == 0); 1066474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1076474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Make sure that there are no register conflicts. 1086474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(!scratch.is(receiver)); 1096474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(!scratch.is(name)); 1106474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(!extra.is(receiver)); 1116474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(!extra.is(name)); 1126474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(!extra.is(scratch)); 1136474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(!extra2.is(receiver)); 1146474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(!extra2.is(name)); 1156474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(!extra2.is(scratch)); 1166474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(!extra2.is(extra)); 1176474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1186474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Check register validity. 1196474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(!scratch.is(no_reg)); 1206474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(!extra.is(no_reg)); 1216474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(!extra2.is(no_reg)); 1226474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org DCHECK(!extra3.is(no_reg)); 1236474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1246474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org Counters* counters = masm->isolate()->counters(); 1256474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, extra2, 1266474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org extra3); 1276474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1286474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Check that the receiver isn't a smi. 1296474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ JumpIfSmi(receiver, &miss); 1306474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1316474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Get the map of the receiver and compute the hash. 1326474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ lw(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); 1336474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ lw(at, FieldMemOperand(receiver, HeapObject::kMapOffset)); 1346474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ Addu(scratch, scratch, at); 1356474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org uint32_t mask = kPrimaryTableSize - 1; 1366474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // We shift out the last two bits because they are not part of the hash and 1376474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // they are always 01 for maps. 1386474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ srl(scratch, scratch, kCacheIndexShift); 1396474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ Xor(scratch, scratch, Operand((flags >> kCacheIndexShift) & mask)); 1406474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ And(scratch, scratch, Operand(mask)); 1416474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1426474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Probe the primary table. 143e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org ProbeTable(isolate, masm, flags, leave_frame, kPrimary, receiver, name, 144e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org scratch, extra, extra2, extra3); 1456474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1466474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Primary miss: Compute hash for secondary probe. 1476474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ srl(at, name, kCacheIndexShift); 1486474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ Subu(scratch, scratch, at); 1496474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org uint32_t mask2 = kSecondaryTableSize - 1; 1506474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ Addu(scratch, scratch, Operand((flags >> kCacheIndexShift) & mask2)); 1516474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ And(scratch, scratch, Operand(mask2)); 1526474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1536474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Probe the secondary table. 154e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org ProbeTable(isolate, masm, flags, leave_frame, kSecondary, receiver, name, 155e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org scratch, extra, extra2, extra3); 1566474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1576474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // Cache miss: Fall-through and let caller handle the miss by 1586474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org // entering the runtime system. 1596474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ bind(&miss); 1606474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, extra2, 1616474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org extra3); 1626474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org} 1636474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1646474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1656474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#undef __ 1666474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org} 1676474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org} // namespace v8::internal 1686474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org 1696474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org#endif // V8_TARGET_ARCH_MIPS 170