| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 SaveFPRegsMode fp_mode, | 245 SaveFPRegsMode fp_mode, |
| 246 RememberedSetAction remembered_set_action, | 246 RememberedSetAction remembered_set_action, |
| 247 SmiCheck smi_check) { | 247 SmiCheck smi_check) { |
| 248 ASSERT(!AreAliased(object, address, value, t8)); | 248 ASSERT(!AreAliased(object, address, value, t8)); |
| 249 ASSERT(!AreAliased(object, address, value, t9)); | 249 ASSERT(!AreAliased(object, address, value, t9)); |
| 250 // The compiled code assumes that record write doesn't change the | 250 // The compiled code assumes that record write doesn't change the |
| 251 // context register, so we check that none of the clobbered | 251 // context register, so we check that none of the clobbered |
| 252 // registers are cp. | 252 // registers are cp. |
| 253 ASSERT(!address.is(cp) && !value.is(cp)); | 253 ASSERT(!address.is(cp) && !value.is(cp)); |
| 254 | 254 |
| 255 if (emit_debug_code()) { |
| 256 lw(at, MemOperand(address)); |
| 257 Assert( |
| 258 eq, "Wrong address or value passed to RecordWrite", at, Operand(value)); |
| 259 } |
| 260 |
| 255 Label done; | 261 Label done; |
| 256 | 262 |
| 257 if (smi_check == INLINE_SMI_CHECK) { | 263 if (smi_check == INLINE_SMI_CHECK) { |
| 258 ASSERT_EQ(0, kSmiTag); | 264 ASSERT_EQ(0, kSmiTag); |
| 259 JumpIfSmi(value, &done); | 265 JumpIfSmi(value, &done); |
| 260 } | 266 } |
| 261 | 267 |
| 262 CheckPageFlag(value, | 268 CheckPageFlag(value, |
| 263 value, // Used as scratch. | 269 value, // Used as scratch. |
| 264 MemoryChunk::kPointersToHereAreInterestingMask, | 270 MemoryChunk::kPointersToHereAreInterestingMask, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 290 } | 296 } |
| 291 } | 297 } |
| 292 | 298 |
| 293 | 299 |
| 294 void MacroAssembler::RememberedSetHelper(Register object, // For debug tests. | 300 void MacroAssembler::RememberedSetHelper(Register object, // For debug tests. |
| 295 Register address, | 301 Register address, |
| 296 Register scratch, | 302 Register scratch, |
| 297 SaveFPRegsMode fp_mode, | 303 SaveFPRegsMode fp_mode, |
| 298 RememberedSetFinalAction and_then) { | 304 RememberedSetFinalAction and_then) { |
| 299 Label done; | 305 Label done; |
| 300 if (FLAG_debug_code) { | 306 if (emit_debug_code()) { |
| 301 Label ok; | 307 Label ok; |
| 302 JumpIfNotInNewSpace(object, scratch, &ok); | 308 JumpIfNotInNewSpace(object, scratch, &ok); |
| 303 stop("Remembered set pointer is in new space"); | 309 stop("Remembered set pointer is in new space"); |
| 304 bind(&ok); | 310 bind(&ok); |
| 305 } | 311 } |
| 306 // Load store buffer top. | 312 // Load store buffer top. |
| 307 ExternalReference store_buffer = | 313 ExternalReference store_buffer = |
| 308 ExternalReference::store_buffer_top(isolate()); | 314 ExternalReference::store_buffer_top(isolate()); |
| 309 li(t8, Operand(store_buffer)); | 315 li(t8, Operand(store_buffer)); |
| 310 lw(scratch, MemOperand(t8)); | 316 lw(scratch, MemOperand(t8)); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 Context::SECURITY_TOKEN_INDEX * kPointerSize; | 408 Context::SECURITY_TOKEN_INDEX * kPointerSize; |
| 403 | 409 |
| 404 lw(scratch, FieldMemOperand(scratch, token_offset)); | 410 lw(scratch, FieldMemOperand(scratch, token_offset)); |
| 405 lw(at, FieldMemOperand(at, token_offset)); | 411 lw(at, FieldMemOperand(at, token_offset)); |
| 406 Branch(miss, ne, scratch, Operand(at)); | 412 Branch(miss, ne, scratch, Operand(at)); |
| 407 | 413 |
| 408 bind(&same_contexts); | 414 bind(&same_contexts); |
| 409 } | 415 } |
| 410 | 416 |
| 411 | 417 |
| 418 void MacroAssembler::GetNumberHash(Register reg0, Register scratch) { |
| 419 // First of all we assign the hash seed to scratch. |
| 420 LoadRoot(scratch, Heap::kHashSeedRootIndex); |
| 421 SmiUntag(scratch); |
| 422 |
| 423 // Xor original key with a seed. |
| 424 xor_(reg0, reg0, scratch); |
| 425 |
| 426 // Compute the hash code from the untagged key. This must be kept in sync |
| 427 // with ComputeIntegerHash in utils.h. |
| 428 // |
| 429 // hash = ~hash + (hash << 15); |
| 430 nor(scratch, reg0, zero_reg); |
| 431 sll(at, reg0, 15); |
| 432 addu(reg0, scratch, at); |
| 433 |
| 434 // hash = hash ^ (hash >> 12); |
| 435 srl(at, reg0, 12); |
| 436 xor_(reg0, reg0, at); |
| 437 |
| 438 // hash = hash + (hash << 2); |
| 439 sll(at, reg0, 2); |
| 440 addu(reg0, reg0, at); |
| 441 |
| 442 // hash = hash ^ (hash >> 4); |
| 443 srl(at, reg0, 4); |
| 444 xor_(reg0, reg0, at); |
| 445 |
| 446 // hash = hash * 2057; |
| 447 li(scratch, Operand(2057)); |
| 448 mul(reg0, reg0, scratch); |
| 449 |
| 450 // hash = hash ^ (hash >> 16); |
| 451 srl(at, reg0, 16); |
| 452 xor_(reg0, reg0, at); |
| 453 } |
| 454 |
| 455 |
| 412 void MacroAssembler::LoadFromNumberDictionary(Label* miss, | 456 void MacroAssembler::LoadFromNumberDictionary(Label* miss, |
| 413 Register elements, | 457 Register elements, |
| 414 Register key, | 458 Register key, |
| 415 Register result, | 459 Register result, |
| 416 Register reg0, | 460 Register reg0, |
| 417 Register reg1, | 461 Register reg1, |
| 418 Register reg2) { | 462 Register reg2) { |
| 419 // Register use: | 463 // Register use: |
| 420 // | 464 // |
| 421 // elements - holds the slow-case elements of the receiver on entry. | 465 // elements - holds the slow-case elements of the receiver on entry. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 433 // Scratch registers: | 477 // Scratch registers: |
| 434 // | 478 // |
| 435 // reg0 - holds the untagged key on entry and holds the hash once computed. | 479 // reg0 - holds the untagged key on entry and holds the hash once computed. |
| 436 // | 480 // |
| 437 // reg1 - Used to hold the capacity mask of the dictionary. | 481 // reg1 - Used to hold the capacity mask of the dictionary. |
| 438 // | 482 // |
| 439 // reg2 - Used for the index into the dictionary. | 483 // reg2 - Used for the index into the dictionary. |
| 440 // at - Temporary (avoid MacroAssembler instructions also using 'at'). | 484 // at - Temporary (avoid MacroAssembler instructions also using 'at'). |
| 441 Label done; | 485 Label done; |
| 442 | 486 |
| 443 // Compute the hash code from the untagged key. This must be kept in sync | 487 GetNumberHash(reg0, reg1); |
| 444 // with ComputeIntegerHash in utils.h. | |
| 445 // | |
| 446 // hash = ~hash + (hash << 15); | |
| 447 nor(reg1, reg0, zero_reg); | |
| 448 sll(at, reg0, 15); | |
| 449 addu(reg0, reg1, at); | |
| 450 | |
| 451 // hash = hash ^ (hash >> 12); | |
| 452 srl(at, reg0, 12); | |
| 453 xor_(reg0, reg0, at); | |
| 454 | |
| 455 // hash = hash + (hash << 2); | |
| 456 sll(at, reg0, 2); | |
| 457 addu(reg0, reg0, at); | |
| 458 | |
| 459 // hash = hash ^ (hash >> 4); | |
| 460 srl(at, reg0, 4); | |
| 461 xor_(reg0, reg0, at); | |
| 462 | |
| 463 // hash = hash * 2057; | |
| 464 li(reg1, Operand(2057)); | |
| 465 mul(reg0, reg0, reg1); | |
| 466 | |
| 467 // hash = hash ^ (hash >> 16); | |
| 468 srl(at, reg0, 16); | |
| 469 xor_(reg0, reg0, at); | |
| 470 | 488 |
| 471 // Compute the capacity mask. | 489 // Compute the capacity mask. |
| 472 lw(reg1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset)); | 490 lw(reg1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); |
| 473 sra(reg1, reg1, kSmiTagSize); | 491 sra(reg1, reg1, kSmiTagSize); |
| 474 Subu(reg1, reg1, Operand(1)); | 492 Subu(reg1, reg1, Operand(1)); |
| 475 | 493 |
| 476 // Generate an unrolled loop that performs a few probes before giving up. | 494 // Generate an unrolled loop that performs a few probes before giving up. |
| 477 static const int kProbes = 4; | 495 static const int kProbes = 4; |
| 478 for (int i = 0; i < kProbes; i++) { | 496 for (int i = 0; i < kProbes; i++) { |
| 479 // Use reg2 for index calculations and keep the hash intact in reg0. | 497 // Use reg2 for index calculations and keep the hash intact in reg0. |
| 480 mov(reg2, reg0); | 498 mov(reg2, reg0); |
| 481 // Compute the masked index: (hash + i + i * i) & mask. | 499 // Compute the masked index: (hash + i + i * i) & mask. |
| 482 if (i > 0) { | 500 if (i > 0) { |
| 483 Addu(reg2, reg2, Operand(NumberDictionary::GetProbeOffset(i))); | 501 Addu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i))); |
| 484 } | 502 } |
| 485 and_(reg2, reg2, reg1); | 503 and_(reg2, reg2, reg1); |
| 486 | 504 |
| 487 // Scale the index by multiplying by the element size. | 505 // Scale the index by multiplying by the element size. |
| 488 ASSERT(NumberDictionary::kEntrySize == 3); | 506 ASSERT(SeededNumberDictionary::kEntrySize == 3); |
| 489 sll(at, reg2, 1); // 2x. | 507 sll(at, reg2, 1); // 2x. |
| 490 addu(reg2, reg2, at); // reg2 = reg2 * 3. | 508 addu(reg2, reg2, at); // reg2 = reg2 * 3. |
| 491 | 509 |
| 492 // Check if the key is identical to the name. | 510 // Check if the key is identical to the name. |
| 493 sll(at, reg2, kPointerSizeLog2); | 511 sll(at, reg2, kPointerSizeLog2); |
| 494 addu(reg2, elements, at); | 512 addu(reg2, elements, at); |
| 495 | 513 |
| 496 lw(at, FieldMemOperand(reg2, NumberDictionary::kElementsStartOffset)); | 514 lw(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset)); |
| 497 if (i != kProbes - 1) { | 515 if (i != kProbes - 1) { |
| 498 Branch(&done, eq, key, Operand(at)); | 516 Branch(&done, eq, key, Operand(at)); |
| 499 } else { | 517 } else { |
| 500 Branch(miss, ne, key, Operand(at)); | 518 Branch(miss, ne, key, Operand(at)); |
| 501 } | 519 } |
| 502 } | 520 } |
| 503 | 521 |
| 504 bind(&done); | 522 bind(&done); |
| 505 // Check that the value is a normal property. | 523 // Check that the value is a normal property. |
| 506 // reg2: elements + (index * kPointerSize). | 524 // reg2: elements + (index * kPointerSize). |
| 507 const int kDetailsOffset = | 525 const int kDetailsOffset = |
| 508 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; | 526 SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; |
| 509 lw(reg1, FieldMemOperand(reg2, kDetailsOffset)); | 527 lw(reg1, FieldMemOperand(reg2, kDetailsOffset)); |
| 510 And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask))); | 528 And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask))); |
| 511 Branch(miss, ne, at, Operand(zero_reg)); | 529 Branch(miss, ne, at, Operand(zero_reg)); |
| 512 | 530 |
| 513 // Get the value at the masked, scaled index and return. | 531 // Get the value at the masked, scaled index and return. |
| 514 const int kValueOffset = | 532 const int kValueOffset = |
| 515 NumberDictionary::kElementsStartOffset + kPointerSize; | 533 SeededNumberDictionary::kElementsStartOffset + kPointerSize; |
| 516 lw(result, FieldMemOperand(reg2, kValueOffset)); | 534 lw(result, FieldMemOperand(reg2, kValueOffset)); |
| 517 } | 535 } |
| 518 | 536 |
| 519 | 537 |
| 520 // --------------------------------------------------------------------------- | 538 // --------------------------------------------------------------------------- |
| 521 // Instruction macros. | 539 // Instruction macros. |
| 522 | 540 |
| 523 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) { | 541 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) { |
| 524 if (rt.is_reg()) { | 542 if (rt.is_reg()) { |
| 525 addu(rd, rs, rt.rm()); | 543 addu(rd, rs, rt.rm()); |
| (...skipping 3728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4254 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 4272 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
| 4255 mov(sp, fp); | 4273 mov(sp, fp); |
| 4256 lw(fp, MemOperand(sp, 0 * kPointerSize)); | 4274 lw(fp, MemOperand(sp, 0 * kPointerSize)); |
| 4257 lw(ra, MemOperand(sp, 1 * kPointerSize)); | 4275 lw(ra, MemOperand(sp, 1 * kPointerSize)); |
| 4258 addiu(sp, sp, 2 * kPointerSize); | 4276 addiu(sp, sp, 2 * kPointerSize); |
| 4259 } | 4277 } |
| 4260 | 4278 |
| 4261 | 4279 |
| 4262 void MacroAssembler::EnterExitFrame(bool save_doubles, | 4280 void MacroAssembler::EnterExitFrame(bool save_doubles, |
| 4263 int stack_space) { | 4281 int stack_space) { |
| 4264 // Setup the frame structure on the stack. | 4282 // Set up the frame structure on the stack. |
| 4265 STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement); | 4283 STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement); |
| 4266 STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset); | 4284 STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset); |
| 4267 STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset); | 4285 STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset); |
| 4268 | 4286 |
| 4269 // This is how the stack will look: | 4287 // This is how the stack will look: |
| 4270 // fp + 2 (==kCallerSPDisplacement) - old stack's end | 4288 // fp + 2 (==kCallerSPDisplacement) - old stack's end |
| 4271 // [fp + 1 (==kCallerPCOffset)] - saved old ra | 4289 // [fp + 1 (==kCallerPCOffset)] - saved old ra |
| 4272 // [fp + 0 (==kCallerFPOffset)] - saved old fp | 4290 // [fp + 0 (==kCallerFPOffset)] - saved old fp |
| 4273 // [fp - 1 (==kSPOffset)] - sp of the called function | 4291 // [fp - 1 (==kSPOffset)] - sp of the called function |
| 4274 // [fp - 2 (==kCodeOffset)] - CodeObject | 4292 // [fp - 2 (==kCodeOffset)] - CodeObject |
| 4275 // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the | 4293 // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the |
| 4276 // new stack (will contain saved ra) | 4294 // new stack (will contain saved ra) |
| 4277 | 4295 |
| 4278 // Save registers. | 4296 // Save registers. |
| 4279 addiu(sp, sp, -4 * kPointerSize); | 4297 addiu(sp, sp, -4 * kPointerSize); |
| 4280 sw(ra, MemOperand(sp, 3 * kPointerSize)); | 4298 sw(ra, MemOperand(sp, 3 * kPointerSize)); |
| 4281 sw(fp, MemOperand(sp, 2 * kPointerSize)); | 4299 sw(fp, MemOperand(sp, 2 * kPointerSize)); |
| 4282 addiu(fp, sp, 2 * kPointerSize); // Setup new frame pointer. | 4300 addiu(fp, sp, 2 * kPointerSize); // Set up new frame pointer. |
| 4283 | 4301 |
| 4284 if (emit_debug_code()) { | 4302 if (emit_debug_code()) { |
| 4285 sw(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 4303 sw(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
| 4286 } | 4304 } |
| 4287 | 4305 |
| 4288 li(t8, Operand(CodeObject())); // Accessed from ExitFrame::code_slot. | 4306 li(t8, Operand(CodeObject())); // Accessed from ExitFrame::code_slot. |
| 4289 sw(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset)); | 4307 sw(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset)); |
| 4290 | 4308 |
| 4291 // Save the frame pointer and the context in top. | 4309 // Save the frame pointer and the context in top. |
| 4292 li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 4310 li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4819 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 4837 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
| 4820 | 4838 |
| 4821 Label done; | 4839 Label done; |
| 4822 | 4840 |
| 4823 // Since both black and grey have a 1 in the first position and white does | 4841 // Since both black and grey have a 1 in the first position and white does |
| 4824 // not have a 1 there we only need to check one bit. | 4842 // not have a 1 there we only need to check one bit. |
| 4825 lw(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 4843 lw(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
| 4826 And(t8, mask_scratch, load_scratch); | 4844 And(t8, mask_scratch, load_scratch); |
| 4827 Branch(&done, ne, t8, Operand(zero_reg)); | 4845 Branch(&done, ne, t8, Operand(zero_reg)); |
| 4828 | 4846 |
| 4829 if (FLAG_debug_code) { | 4847 if (emit_debug_code()) { |
| 4830 // Check for impossible bit pattern. | 4848 // Check for impossible bit pattern. |
| 4831 Label ok; | 4849 Label ok; |
| 4832 // sll may overflow, making the check conservative. | 4850 // sll may overflow, making the check conservative. |
| 4833 sll(t8, mask_scratch, 1); | 4851 sll(t8, mask_scratch, 1); |
| 4834 And(t8, load_scratch, t8); | 4852 And(t8, load_scratch, t8); |
| 4835 Branch(&ok, eq, t8, Operand(zero_reg)); | 4853 Branch(&ok, eq, t8, Operand(zero_reg)); |
| 4836 stop("Impossible marking bit pattern"); | 4854 stop("Impossible marking bit pattern"); |
| 4837 bind(&ok); | 4855 bind(&ok); |
| 4838 } | 4856 } |
| 4839 | 4857 |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5027 opcode == BGTZL); | 5045 opcode == BGTZL); |
| 5028 opcode = (cond == eq) ? BEQ : BNE; | 5046 opcode = (cond == eq) ? BEQ : BNE; |
| 5029 instr = (instr & ~kOpcodeMask) | opcode; | 5047 instr = (instr & ~kOpcodeMask) | opcode; |
| 5030 masm_.emit(instr); | 5048 masm_.emit(instr); |
| 5031 } | 5049 } |
| 5032 | 5050 |
| 5033 | 5051 |
| 5034 } } // namespace v8::internal | 5052 } } // namespace v8::internal |
| 5035 | 5053 |
| 5036 #endif // V8_TARGET_ARCH_MIPS | 5054 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |