1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_MIPS_CODE_STUBS_ARM_H_ 29 #define V8_MIPS_CODE_STUBS_ARM_H_ 30 31 #include "ic-inl.h" 32 33 34 namespace v8 { 35 namespace internal { 36 37 38 void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code); 39 40 41 // Compute a transcendental math function natively, or call the 42 // TranscendentalCache runtime function. 43 class TranscendentalCacheStub: public PlatformCodeStub { 44 public: 45 enum ArgumentType { 46 TAGGED = 0 << TranscendentalCache::kTranscendentalTypeBits, 47 UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits 48 }; 49 50 TranscendentalCacheStub(TranscendentalCache::Type type, 51 ArgumentType argument_type) 52 : type_(type), argument_type_(argument_type) { } 53 void Generate(MacroAssembler* masm); 54 private: 55 TranscendentalCache::Type type_; 56 ArgumentType argument_type_; 57 void GenerateCallCFunction(MacroAssembler* masm, Register scratch); 58 59 Major MajorKey() { return TranscendentalCache; } 60 int MinorKey() { return type_ | argument_type_; } 61 Runtime::FunctionId RuntimeFunction(); 62 }; 63 64 65 class StoreBufferOverflowStub: public PlatformCodeStub { 66 public: 67 explicit StoreBufferOverflowStub(SaveFPRegsMode save_fp) 68 : save_doubles_(save_fp) {} 69 70 void Generate(MacroAssembler* masm); 71 72 virtual bool IsPregenerated() { return true; } 73 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate); 74 virtual bool SometimesSetsUpAFrame() { return false; } 75 76 private: 77 SaveFPRegsMode save_doubles_; 78 79 Major MajorKey() { return StoreBufferOverflow; } 80 int MinorKey() { return (save_doubles_ == kSaveFPRegs) ? 1 : 0; } 81 }; 82 83 84 class StringHelper : public AllStatic { 85 public: 86 // Generate code for copying characters using a simple loop. This should only 87 // be used in places where the number of characters is small and the 88 // additional setup and checking in GenerateCopyCharactersLong adds too much 89 // overhead. Copying of overlapping regions is not supported. 90 // Dest register ends at the position after the last character written. 91 static void GenerateCopyCharacters(MacroAssembler* masm, 92 Register dest, 93 Register src, 94 Register count, 95 Register scratch, 96 bool ascii); 97 98 // Generate code for copying a large number of characters. This function 99 // is allowed to spend extra time setting up conditions to make copying 100 // faster. Copying of overlapping regions is not supported. 101 // Dest register ends at the position after the last character written. 102 static void GenerateCopyCharactersLong(MacroAssembler* masm, 103 Register dest, 104 Register src, 105 Register count, 106 Register scratch1, 107 Register scratch2, 108 Register scratch3, 109 Register scratch4, 110 Register scratch5, 111 int flags); 112 113 114 // Probe the string table for a two character string. If the string is 115 // not found by probing a jump to the label not_found is performed. This jump 116 // does not guarantee that the string is not in the string table. If the 117 // string is found the code falls through with the string in register r0. 118 // Contents of both c1 and c2 registers are modified. At the exit c1 is 119 // guaranteed to contain halfword with low and high bytes equal to 120 // initial contents of c1 and c2 respectively. 121 static void GenerateTwoCharacterStringTableProbe(MacroAssembler* masm, 122 Register c1, 123 Register c2, 124 Register scratch1, 125 Register scratch2, 126 Register scratch3, 127 Register scratch4, 128 Register scratch5, 129 Label* not_found); 130 131 // Generate string hash. 132 static void GenerateHashInit(MacroAssembler* masm, 133 Register hash, 134 Register character); 135 136 static void GenerateHashAddCharacter(MacroAssembler* masm, 137 Register hash, 138 Register character); 139 140 static void GenerateHashGetHash(MacroAssembler* masm, 141 Register hash); 142 143 private: 144 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper); 145 }; 146 147 148 class StringAddStub: public PlatformCodeStub { 149 public: 150 explicit StringAddStub(StringAddFlags flags) : flags_(flags) {} 151 152 private: 153 Major MajorKey() { return StringAdd; } 154 int MinorKey() { return flags_; } 155 156 void Generate(MacroAssembler* masm); 157 158 void GenerateConvertArgument(MacroAssembler* masm, 159 int stack_offset, 160 Register arg, 161 Register scratch1, 162 Register scratch2, 163 Register scratch3, 164 Register scratch4, 165 Label* slow); 166 167 void GenerateRegisterArgsPush(MacroAssembler* masm); 168 void GenerateRegisterArgsPop(MacroAssembler* masm); 169 170 const StringAddFlags flags_; 171 }; 172 173 174 class SubStringStub: public PlatformCodeStub { 175 public: 176 SubStringStub() {} 177 178 private: 179 Major MajorKey() { return SubString; } 180 int MinorKey() { return 0; } 181 182 void Generate(MacroAssembler* masm); 183 }; 184 185 186 class StringCompareStub: public PlatformCodeStub { 187 public: 188 StringCompareStub() { } 189 190 // Compare two flat ASCII strings and returns result in v0. 191 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 192 Register left, 193 Register right, 194 Register scratch1, 195 Register scratch2, 196 Register scratch3, 197 Register scratch4); 198 199 // Compares two flat ASCII strings for equality and returns result 200 // in v0. 201 static void GenerateFlatAsciiStringEquals(MacroAssembler* masm, 202 Register left, 203 Register right, 204 Register scratch1, 205 Register scratch2, 206 Register scratch3); 207 208 private: 209 virtual Major MajorKey() { return StringCompare; } 210 virtual int MinorKey() { return 0; } 211 virtual void Generate(MacroAssembler* masm); 212 213 static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm, 214 Register left, 215 Register right, 216 Register length, 217 Register scratch1, 218 Register scratch2, 219 Register scratch3, 220 Label* chars_not_equal); 221 }; 222 223 224 // This stub can convert a signed int32 to a heap number (double). It does 225 // not work for int32s that are in Smi range! No GC occurs during this stub 226 // so you don't have to set up the frame. 227 class WriteInt32ToHeapNumberStub : public PlatformCodeStub { 228 public: 229 WriteInt32ToHeapNumberStub(Register the_int, 230 Register the_heap_number, 231 Register scratch, 232 Register scratch2) 233 : the_int_(the_int), 234 the_heap_number_(the_heap_number), 235 scratch_(scratch), 236 sign_(scratch2) { 237 ASSERT(IntRegisterBits::is_valid(the_int_.code())); 238 ASSERT(HeapNumberRegisterBits::is_valid(the_heap_number_.code())); 239 ASSERT(ScratchRegisterBits::is_valid(scratch_.code())); 240 ASSERT(SignRegisterBits::is_valid(sign_.code())); 241 } 242 243 bool IsPregenerated(); 244 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate); 245 246 private: 247 Register the_int_; 248 Register the_heap_number_; 249 Register scratch_; 250 Register sign_; 251 252 // Minor key encoding in 16 bits. 253 class IntRegisterBits: public BitField<int, 0, 4> {}; 254 class HeapNumberRegisterBits: public BitField<int, 4, 4> {}; 255 class ScratchRegisterBits: public BitField<int, 8, 4> {}; 256 class SignRegisterBits: public BitField<int, 12, 4> {}; 257 258 Major MajorKey() { return WriteInt32ToHeapNumber; } 259 int MinorKey() { 260 // Encode the parameters in a unique 16 bit value. 261 return IntRegisterBits::encode(the_int_.code()) 262 | HeapNumberRegisterBits::encode(the_heap_number_.code()) 263 | ScratchRegisterBits::encode(scratch_.code()) 264 | SignRegisterBits::encode(sign_.code()); 265 } 266 267 void Generate(MacroAssembler* masm); 268 }; 269 270 271 class NumberToStringStub: public PlatformCodeStub { 272 public: 273 NumberToStringStub() { } 274 275 // Generate code to do a lookup in the number string cache. If the number in 276 // the register object is found in the cache the generated code falls through 277 // with the result in the result register. The object and the result register 278 // can be the same. If the number is not found in the cache the code jumps to 279 // the label not_found with only the content of register object unchanged. 280 static void GenerateLookupNumberStringCache(MacroAssembler* masm, 281 Register object, 282 Register result, 283 Register scratch1, 284 Register scratch2, 285 Register scratch3, 286 Label* not_found); 287 288 private: 289 Major MajorKey() { return NumberToString; } 290 int MinorKey() { return 0; } 291 292 void Generate(MacroAssembler* masm); 293 }; 294 295 296 class RecordWriteStub: public PlatformCodeStub { 297 public: 298 RecordWriteStub(Register object, 299 Register value, 300 Register address, 301 RememberedSetAction remembered_set_action, 302 SaveFPRegsMode fp_mode) 303 : object_(object), 304 value_(value), 305 address_(address), 306 remembered_set_action_(remembered_set_action), 307 save_fp_regs_mode_(fp_mode), 308 regs_(object, // An input reg. 309 address, // An input reg. 310 value) { // One scratch reg. 311 } 312 313 enum Mode { 314 STORE_BUFFER_ONLY, 315 INCREMENTAL, 316 INCREMENTAL_COMPACTION 317 }; 318 319 virtual bool IsPregenerated(); 320 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate); 321 virtual bool SometimesSetsUpAFrame() { return false; } 322 323 static void PatchBranchIntoNop(MacroAssembler* masm, int pos) { 324 const unsigned offset = masm->instr_at(pos) & kImm16Mask; 325 masm->instr_at_put(pos, BNE | (zero_reg.code() << kRsShift) | 326 (zero_reg.code() << kRtShift) | (offset & kImm16Mask)); 327 ASSERT(Assembler::IsBne(masm->instr_at(pos))); 328 } 329 330 static void PatchNopIntoBranch(MacroAssembler* masm, int pos) { 331 const unsigned offset = masm->instr_at(pos) & kImm16Mask; 332 masm->instr_at_put(pos, BEQ | (zero_reg.code() << kRsShift) | 333 (zero_reg.code() << kRtShift) | (offset & kImm16Mask)); 334 ASSERT(Assembler::IsBeq(masm->instr_at(pos))); 335 } 336 337 static Mode GetMode(Code* stub) { 338 Instr first_instruction = Assembler::instr_at(stub->instruction_start()); 339 Instr second_instruction = Assembler::instr_at(stub->instruction_start() + 340 2 * Assembler::kInstrSize); 341 342 if (Assembler::IsBeq(first_instruction)) { 343 return INCREMENTAL; 344 } 345 346 ASSERT(Assembler::IsBne(first_instruction)); 347 348 if (Assembler::IsBeq(second_instruction)) { 349 return INCREMENTAL_COMPACTION; 350 } 351 352 ASSERT(Assembler::IsBne(second_instruction)); 353 354 return STORE_BUFFER_ONLY; 355 } 356 357 static void Patch(Code* stub, Mode mode) { 358 MacroAssembler masm(NULL, 359 stub->instruction_start(), 360 stub->instruction_size()); 361 switch (mode) { 362 case STORE_BUFFER_ONLY: 363 ASSERT(GetMode(stub) == INCREMENTAL || 364 GetMode(stub) == INCREMENTAL_COMPACTION); 365 PatchBranchIntoNop(&masm, 0); 366 PatchBranchIntoNop(&masm, 2 * Assembler::kInstrSize); 367 break; 368 case INCREMENTAL: 369 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY); 370 PatchNopIntoBranch(&masm, 0); 371 break; 372 case INCREMENTAL_COMPACTION: 373 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY); 374 PatchNopIntoBranch(&masm, 2 * Assembler::kInstrSize); 375 break; 376 } 377 ASSERT(GetMode(stub) == mode); 378 CPU::FlushICache(stub->instruction_start(), 4 * Assembler::kInstrSize); 379 } 380 381 private: 382 // This is a helper class for freeing up 3 scratch registers. The input is 383 // two registers that must be preserved and one scratch register provided by 384 // the caller. 385 class RegisterAllocation { 386 public: 387 RegisterAllocation(Register object, 388 Register address, 389 Register scratch0) 390 : object_(object), 391 address_(address), 392 scratch0_(scratch0) { 393 ASSERT(!AreAliased(scratch0, object, address, no_reg)); 394 scratch1_ = GetRegThatIsNotOneOf(object_, address_, scratch0_); 395 } 396 397 void Save(MacroAssembler* masm) { 398 ASSERT(!AreAliased(object_, address_, scratch1_, scratch0_)); 399 // We don't have to save scratch0_ because it was given to us as 400 // a scratch register. 401 masm->push(scratch1_); 402 } 403 404 void Restore(MacroAssembler* masm) { 405 masm->pop(scratch1_); 406 } 407 408 // If we have to call into C then we need to save and restore all caller- 409 // saved registers that were not already preserved. The scratch registers 410 // will be restored by other means so we don't bother pushing them here. 411 void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) { 412 masm->MultiPush((kJSCallerSaved | ra.bit()) & ~scratch1_.bit()); 413 if (mode == kSaveFPRegs) { 414 masm->MultiPushFPU(kCallerSavedFPU); 415 } 416 } 417 418 inline void RestoreCallerSaveRegisters(MacroAssembler*masm, 419 SaveFPRegsMode mode) { 420 if (mode == kSaveFPRegs) { 421 masm->MultiPopFPU(kCallerSavedFPU); 422 } 423 masm->MultiPop((kJSCallerSaved | ra.bit()) & ~scratch1_.bit()); 424 } 425 426 inline Register object() { return object_; } 427 inline Register address() { return address_; } 428 inline Register scratch0() { return scratch0_; } 429 inline Register scratch1() { return scratch1_; } 430 431 private: 432 Register object_; 433 Register address_; 434 Register scratch0_; 435 Register scratch1_; 436 437 Register GetRegThatIsNotOneOf(Register r1, 438 Register r2, 439 Register r3) { 440 for (int i = 0; i < Register::NumAllocatableRegisters(); i++) { 441 Register candidate = Register::FromAllocationIndex(i); 442 if (candidate.is(r1)) continue; 443 if (candidate.is(r2)) continue; 444 if (candidate.is(r3)) continue; 445 return candidate; 446 } 447 UNREACHABLE(); 448 return no_reg; 449 } 450 friend class RecordWriteStub; 451 }; 452 453 enum OnNoNeedToInformIncrementalMarker { 454 kReturnOnNoNeedToInformIncrementalMarker, 455 kUpdateRememberedSetOnNoNeedToInformIncrementalMarker 456 }; 457 458 void Generate(MacroAssembler* masm); 459 void GenerateIncremental(MacroAssembler* masm, Mode mode); 460 void CheckNeedsToInformIncrementalMarker( 461 MacroAssembler* masm, 462 OnNoNeedToInformIncrementalMarker on_no_need, 463 Mode mode); 464 void InformIncrementalMarker(MacroAssembler* masm, Mode mode); 465 466 Major MajorKey() { return RecordWrite; } 467 468 int MinorKey() { 469 return ObjectBits::encode(object_.code()) | 470 ValueBits::encode(value_.code()) | 471 AddressBits::encode(address_.code()) | 472 RememberedSetActionBits::encode(remembered_set_action_) | 473 SaveFPRegsModeBits::encode(save_fp_regs_mode_); 474 } 475 476 void Activate(Code* code) { 477 code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code); 478 } 479 480 class ObjectBits: public BitField<int, 0, 5> {}; 481 class ValueBits: public BitField<int, 5, 5> {}; 482 class AddressBits: public BitField<int, 10, 5> {}; 483 class RememberedSetActionBits: public BitField<RememberedSetAction, 15, 1> {}; 484 class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 16, 1> {}; 485 486 Register object_; 487 Register value_; 488 Register address_; 489 RememberedSetAction remembered_set_action_; 490 SaveFPRegsMode save_fp_regs_mode_; 491 Label slow_; 492 RegisterAllocation regs_; 493 }; 494 495 496 // Enter C code from generated RegExp code in a way that allows 497 // the C code to fix the return address in case of a GC. 498 // Currently only needed on ARM and MIPS. 499 class RegExpCEntryStub: public PlatformCodeStub { 500 public: 501 RegExpCEntryStub() {} 502 virtual ~RegExpCEntryStub() {} 503 void Generate(MacroAssembler* masm); 504 505 private: 506 Major MajorKey() { return RegExpCEntry; } 507 int MinorKey() { return 0; } 508 509 bool NeedsImmovableCode() { return true; } 510 }; 511 512 // Trampoline stub to call into native code. To call safely into native code 513 // in the presence of compacting GC (which can move code objects) we need to 514 // keep the code which called into native pinned in the memory. Currently the 515 // simplest approach is to generate such stub early enough so it can never be 516 // moved by GC 517 class DirectCEntryStub: public PlatformCodeStub { 518 public: 519 DirectCEntryStub() {} 520 void Generate(MacroAssembler* masm); 521 void GenerateCall(MacroAssembler* masm, Register target); 522 523 private: 524 Major MajorKey() { return DirectCEntry; } 525 int MinorKey() { return 0; } 526 527 bool NeedsImmovableCode() { return true; } 528 }; 529 530 class FloatingPointHelper : public AllStatic { 531 public: 532 enum Destination { 533 kFPURegisters, 534 kCoreRegisters 535 }; 536 537 538 // Loads smis from a0 and a1 (right and left in binary operations) into 539 // floating point registers. Depending on the destination the values ends up 540 // either f14 and f12 or in a2/a3 and a0/a1 respectively. If the destination 541 // is floating point registers FPU must be supported. If core registers are 542 // requested when FPU is supported f12 and f14 will be scratched. 543 static void LoadSmis(MacroAssembler* masm, 544 Destination destination, 545 Register scratch1, 546 Register scratch2); 547 548 // Convert the smi or heap number in object to an int32 using the rules 549 // for ToInt32 as described in ECMAScript 9.5.: the value is truncated 550 // and brought into the range -2^31 .. +2^31 - 1. 551 static void ConvertNumberToInt32(MacroAssembler* masm, 552 Register object, 553 Register dst, 554 Register heap_number_map, 555 Register scratch1, 556 Register scratch2, 557 Register scratch3, 558 FPURegister double_scratch, 559 Label* not_int32); 560 561 // Converts the integer (untagged smi) in |int_scratch| to a double, storing 562 // the result either in |double_dst| or |dst2:dst1|, depending on 563 // |destination|. 564 // Warning: The value in |int_scratch| will be changed in the process! 565 static void ConvertIntToDouble(MacroAssembler* masm, 566 Register int_scratch, 567 Destination destination, 568 FPURegister double_dst, 569 Register dst1, 570 Register dst2, 571 Register scratch2, 572 FPURegister single_scratch); 573 574 // Load the number from object into double_dst in the double format. 575 // Control will jump to not_int32 if the value cannot be exactly represented 576 // by a 32-bit integer. 577 // Floating point value in the 32-bit integer range that are not exact integer 578 // won't be loaded. 579 static void LoadNumberAsInt32Double(MacroAssembler* masm, 580 Register object, 581 Destination destination, 582 FPURegister double_dst, 583 FPURegister double_scratch, 584 Register dst1, 585 Register dst2, 586 Register heap_number_map, 587 Register scratch1, 588 Register scratch2, 589 FPURegister single_scratch, 590 Label* not_int32); 591 592 // Loads the number from object into dst as a 32-bit integer. 593 // Control will jump to not_int32 if the object cannot be exactly represented 594 // by a 32-bit integer. 595 // Floating point value in the 32-bit integer range that are not exact integer 596 // won't be converted. 597 // scratch3 is not used when FPU is supported. 598 static void LoadNumberAsInt32(MacroAssembler* masm, 599 Register object, 600 Register dst, 601 Register heap_number_map, 602 Register scratch1, 603 Register scratch2, 604 Register scratch3, 605 FPURegister double_scratch0, 606 FPURegister double_scratch1, 607 Label* not_int32); 608 609 // Generates code to call a C function to do a double operation using core 610 // registers. (Used when FPU is not supported.) 611 // This code never falls through, but returns with a heap number containing 612 // the result in v0. 613 // Register heapnumber_result must be a heap number in which the 614 // result of the operation will be stored. 615 // Requires the following layout on entry: 616 // a0: Left value (least significant part of mantissa). 617 // a1: Left value (sign, exponent, top of mantissa). 618 // a2: Right value (least significant part of mantissa). 619 // a3: Right value (sign, exponent, top of mantissa). 620 static void CallCCodeForDoubleOperation(MacroAssembler* masm, 621 Token::Value op, 622 Register heap_number_result, 623 Register scratch); 624 625 // Loads the objects from |object| into floating point registers. 626 // Depending on |destination| the value ends up either in |dst| or 627 // in |dst1|/|dst2|. If |destination| is kFPURegisters, then FPU 628 // must be supported. If kCoreRegisters are requested and FPU is 629 // supported, |dst| will be scratched. If |object| is neither smi nor 630 // heap number, |not_number| is jumped to with |object| still intact. 631 static void LoadNumber(MacroAssembler* masm, 632 FloatingPointHelper::Destination destination, 633 Register object, 634 FPURegister dst, 635 Register dst1, 636 Register dst2, 637 Register heap_number_map, 638 Register scratch1, 639 Register scratch2, 640 Label* not_number); 641 }; 642 643 644 class NameDictionaryLookupStub: public PlatformCodeStub { 645 public: 646 enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP }; 647 648 explicit NameDictionaryLookupStub(LookupMode mode) : mode_(mode) { } 649 650 void Generate(MacroAssembler* masm); 651 652 static void GenerateNegativeLookup(MacroAssembler* masm, 653 Label* miss, 654 Label* done, 655 Register receiver, 656 Register properties, 657 Handle<Name> name, 658 Register scratch0); 659 660 static void GeneratePositiveLookup(MacroAssembler* masm, 661 Label* miss, 662 Label* done, 663 Register elements, 664 Register name, 665 Register r0, 666 Register r1); 667 668 virtual bool SometimesSetsUpAFrame() { return false; } 669 670 private: 671 static const int kInlinedProbes = 4; 672 static const int kTotalProbes = 20; 673 674 static const int kCapacityOffset = 675 NameDictionary::kHeaderSize + 676 NameDictionary::kCapacityIndex * kPointerSize; 677 678 static const int kElementsStartOffset = 679 NameDictionary::kHeaderSize + 680 NameDictionary::kElementsStartIndex * kPointerSize; 681 682 Major MajorKey() { return NameDictionaryLookup; } 683 684 int MinorKey() { 685 return LookupModeBits::encode(mode_); 686 } 687 688 class LookupModeBits: public BitField<LookupMode, 0, 1> {}; 689 690 LookupMode mode_; 691 }; 692 693 694 } } // namespace v8::internal 695 696 #endif // V8_MIPS_CODE_STUBS_ARM_H_ 697