| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 Label done; | 503 Label done; |
| 504 | 504 |
| 505 GetNumberHash(reg0, reg1); | 505 GetNumberHash(reg0, reg1); |
| 506 | 506 |
| 507 // Compute the capacity mask. | 507 // Compute the capacity mask. |
| 508 lw(reg1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); | 508 lw(reg1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); |
| 509 sra(reg1, reg1, kSmiTagSize); | 509 sra(reg1, reg1, kSmiTagSize); |
| 510 Subu(reg1, reg1, Operand(1)); | 510 Subu(reg1, reg1, Operand(1)); |
| 511 | 511 |
| 512 // Generate an unrolled loop that performs a few probes before giving up. | 512 // Generate an unrolled loop that performs a few probes before giving up. |
| 513 static const int kProbes = 4; | 513 for (int i = 0; i < kNumberDictionaryProbes; i++) { |
| 514 for (int i = 0; i < kProbes; i++) { | |
| 515 // Use reg2 for index calculations and keep the hash intact in reg0. | 514 // Use reg2 for index calculations and keep the hash intact in reg0. |
| 516 mov(reg2, reg0); | 515 mov(reg2, reg0); |
| 517 // Compute the masked index: (hash + i + i * i) & mask. | 516 // Compute the masked index: (hash + i + i * i) & mask. |
| 518 if (i > 0) { | 517 if (i > 0) { |
| 519 Addu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i))); | 518 Addu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i))); |
| 520 } | 519 } |
| 521 and_(reg2, reg2, reg1); | 520 and_(reg2, reg2, reg1); |
| 522 | 521 |
| 523 // Scale the index by multiplying by the element size. | 522 // Scale the index by multiplying by the element size. |
| 524 ASSERT(SeededNumberDictionary::kEntrySize == 3); | 523 ASSERT(SeededNumberDictionary::kEntrySize == 3); |
| 525 sll(at, reg2, 1); // 2x. | 524 sll(at, reg2, 1); // 2x. |
| 526 addu(reg2, reg2, at); // reg2 = reg2 * 3. | 525 addu(reg2, reg2, at); // reg2 = reg2 * 3. |
| 527 | 526 |
| 528 // Check if the key is identical to the name. | 527 // Check if the key is identical to the name. |
| 529 sll(at, reg2, kPointerSizeLog2); | 528 sll(at, reg2, kPointerSizeLog2); |
| 530 addu(reg2, elements, at); | 529 addu(reg2, elements, at); |
| 531 | 530 |
| 532 lw(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset)); | 531 lw(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset)); |
| 533 if (i != kProbes - 1) { | 532 if (i != kNumberDictionaryProbes - 1) { |
| 534 Branch(&done, eq, key, Operand(at)); | 533 Branch(&done, eq, key, Operand(at)); |
| 535 } else { | 534 } else { |
| 536 Branch(miss, ne, key, Operand(at)); | 535 Branch(miss, ne, key, Operand(at)); |
| 537 } | 536 } |
| 538 } | 537 } |
| 539 | 538 |
| 540 bind(&done); | 539 bind(&done); |
| 541 // Check that the value is a normal property. | 540 // Check that the value is a normal property. |
| 542 // reg2: elements + (index * kPointerSize). | 541 // reg2: elements + (index * kPointerSize). |
| 543 const int kDetailsOffset = | 542 const int kDetailsOffset = |
| (...skipping 3961 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4505 Label ok, fail; | 4504 Label ok, fail; |
| 4506 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); | 4505 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); |
| 4507 Branch(&ok); | 4506 Branch(&ok); |
| 4508 bind(&fail); | 4507 bind(&fail); |
| 4509 Abort(kGlobalFunctionsMustHaveInitialMap); | 4508 Abort(kGlobalFunctionsMustHaveInitialMap); |
| 4510 bind(&ok); | 4509 bind(&ok); |
| 4511 } | 4510 } |
| 4512 } | 4511 } |
| 4513 | 4512 |
| 4514 | 4513 |
| 4515 void MacroAssembler::LoadNumber(Register object, | |
| 4516 FPURegister dst, | |
| 4517 Register heap_number_map, | |
| 4518 Register scratch, | |
| 4519 Label* not_number) { | |
| 4520 Label is_smi, done; | |
| 4521 | |
| 4522 UntagAndJumpIfSmi(scratch, object, &is_smi); | |
| 4523 JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number); | |
| 4524 | |
| 4525 ldc1(dst, FieldMemOperand(object, HeapNumber::kValueOffset)); | |
| 4526 Branch(&done); | |
| 4527 | |
| 4528 bind(&is_smi); | |
| 4529 mtc1(scratch, dst); | |
| 4530 cvt_d_w(dst, dst); | |
| 4531 | |
| 4532 bind(&done); | |
| 4533 } | |
| 4534 | |
| 4535 | |
| 4536 void MacroAssembler::LoadNumberAsInt32Double(Register object, | |
| 4537 DoubleRegister double_dst, | |
| 4538 Register heap_number_map, | |
| 4539 Register scratch1, | |
| 4540 Register scratch2, | |
| 4541 FPURegister double_scratch, | |
| 4542 Label* not_int32) { | |
| 4543 ASSERT(!scratch1.is(object) && !scratch2.is(object)); | |
| 4544 ASSERT(!scratch1.is(scratch2)); | |
| 4545 ASSERT(!heap_number_map.is(object) && | |
| 4546 !heap_number_map.is(scratch1) && | |
| 4547 !heap_number_map.is(scratch2)); | |
| 4548 | |
| 4549 Label done, obj_is_not_smi; | |
| 4550 | |
| 4551 UntagAndJumpIfNotSmi(scratch1, object, &obj_is_not_smi); | |
| 4552 mtc1(scratch1, double_scratch); | |
| 4553 cvt_d_w(double_dst, double_scratch); | |
| 4554 Branch(&done); | |
| 4555 | |
| 4556 bind(&obj_is_not_smi); | |
| 4557 JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); | |
| 4558 | |
| 4559 // Load the number. | |
| 4560 // Load the double value. | |
| 4561 ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset)); | |
| 4562 | |
| 4563 Register except_flag = scratch2; | |
| 4564 EmitFPUTruncate(kRoundToZero, | |
| 4565 scratch1, | |
| 4566 double_dst, | |
| 4567 at, | |
| 4568 double_scratch, | |
| 4569 except_flag, | |
| 4570 kCheckForInexactConversion); | |
| 4571 | |
| 4572 // Jump to not_int32 if the operation did not succeed. | |
| 4573 Branch(not_int32, ne, except_flag, Operand(zero_reg)); | |
| 4574 bind(&done); | |
| 4575 } | |
| 4576 | |
| 4577 | |
| 4578 void MacroAssembler::LoadNumberAsInt32(Register object, | |
| 4579 Register dst, | |
| 4580 Register heap_number_map, | |
| 4581 Register scratch1, | |
| 4582 Register scratch2, | |
| 4583 FPURegister double_scratch0, | |
| 4584 FPURegister double_scratch1, | |
| 4585 Label* not_int32) { | |
| 4586 ASSERT(!dst.is(object)); | |
| 4587 ASSERT(!scratch1.is(object) && !scratch2.is(object)); | |
| 4588 ASSERT(!scratch1.is(scratch2)); | |
| 4589 | |
| 4590 Label done, maybe_undefined; | |
| 4591 | |
| 4592 UntagAndJumpIfSmi(dst, object, &done); | |
| 4593 | |
| 4594 JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined); | |
| 4595 | |
| 4596 // Object is a heap number. | |
| 4597 // Convert the floating point value to a 32-bit integer. | |
| 4598 // Load the double value. | |
| 4599 ldc1(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset)); | |
| 4600 | |
| 4601 Register except_flag = scratch2; | |
| 4602 EmitFPUTruncate(kRoundToZero, | |
| 4603 dst, | |
| 4604 double_scratch0, | |
| 4605 scratch1, | |
| 4606 double_scratch1, | |
| 4607 except_flag, | |
| 4608 kCheckForInexactConversion); | |
| 4609 | |
| 4610 // Jump to not_int32 if the operation did not succeed. | |
| 4611 Branch(not_int32, ne, except_flag, Operand(zero_reg)); | |
| 4612 Branch(&done); | |
| 4613 | |
| 4614 bind(&maybe_undefined); | |
| 4615 LoadRoot(at, Heap::kUndefinedValueRootIndex); | |
| 4616 Branch(not_int32, ne, object, Operand(at)); | |
| 4617 // |undefined| is truncated to 0. | |
| 4618 li(dst, Operand(Smi::FromInt(0))); | |
| 4619 // Fall through. | |
| 4620 | |
| 4621 bind(&done); | |
| 4622 } | |
| 4623 | |
| 4624 | |
| 4625 void MacroAssembler::Prologue(PrologueFrameMode frame_mode) { | 4514 void MacroAssembler::Prologue(PrologueFrameMode frame_mode) { |
| 4626 if (frame_mode == BUILD_STUB_FRAME) { | 4515 if (frame_mode == BUILD_STUB_FRAME) { |
| 4627 Push(ra, fp, cp); | 4516 Push(ra, fp, cp); |
| 4628 Push(Smi::FromInt(StackFrame::STUB)); | 4517 Push(Smi::FromInt(StackFrame::STUB)); |
| 4629 // Adjust FP to point to saved FP. | 4518 // Adjust FP to point to saved FP. |
| 4630 Addu(fp, sp, Operand(2 * kPointerSize)); | 4519 Addu(fp, sp, Operand(2 * kPointerSize)); |
| 4631 } else { | 4520 } else { |
| 4632 PredictableCodeSizeScope predictible_code_size_scope( | 4521 PredictableCodeSizeScope predictible_code_size_scope( |
| 4633 this, kNoCodeAgeSequenceLength * Assembler::kInstrSize); | 4522 this, kNoCodeAgeSequenceLength * Assembler::kInstrSize); |
| 4634 // The following three instructions must remain together and unmodified | 4523 // The following three instructions must remain together and unmodified |
| (...skipping 1135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5770 opcode == BGTZL); | 5659 opcode == BGTZL); |
| 5771 opcode = (cond == eq) ? BEQ : BNE; | 5660 opcode = (cond == eq) ? BEQ : BNE; |
| 5772 instr = (instr & ~kOpcodeMask) | opcode; | 5661 instr = (instr & ~kOpcodeMask) | opcode; |
| 5773 masm_.emit(instr); | 5662 masm_.emit(instr); |
| 5774 } | 5663 } |
| 5775 | 5664 |
| 5776 | 5665 |
| 5777 } } // namespace v8::internal | 5666 } } // namespace v8::internal |
| 5778 | 5667 |
| 5779 #endif // V8_TARGET_ARCH_MIPS | 5668 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |