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