| 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(StandardFrameConstants::kFixedFrameSizeFromFp)); |
| 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 |
| 4635 // for code aging to work properly. | 4524 // for code aging to work properly. |
| 4636 if (isolate()->IsCodePreAgingActive()) { | 4525 if (isolate()->IsCodePreAgingActive()) { |
| 4637 // Pre-age the code. | 4526 // Pre-age the code. |
| 4638 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); | 4527 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); |
| 4639 nop(Assembler::CODE_AGE_MARKER_NOP); | 4528 nop(Assembler::CODE_AGE_MARKER_NOP); |
| 4640 // Save the function's original return address | 4529 // Save the function's original return address |
| 4641 // (it will be clobbered by Call(t9)). | 4530 // (it will be clobbered by Call(t9)). |
| 4642 mov(at, ra); | 4531 mov(at, ra); |
| 4643 // Load the stub address to t9 and call it. | 4532 // Load the stub address to t9 and call it. |
| 4644 li(t9, | 4533 li(t9, |
| 4645 Operand(reinterpret_cast<uint32_t>(stub->instruction_start()))); | 4534 Operand(reinterpret_cast<uint32_t>(stub->instruction_start()))); |
| 4646 Call(t9); | 4535 Call(t9); |
| 4647 // Record the stub address in the empty space for GetCodeAgeAndParity(). | 4536 // Record the stub address in the empty space for GetCodeAgeAndParity(). |
| 4648 emit_code_stub_address(stub); | 4537 emit_code_stub_address(stub); |
| 4649 } else { | 4538 } else { |
| 4650 Push(ra, fp, cp, a1); | 4539 Push(ra, fp, cp, a1); |
| 4651 nop(Assembler::CODE_AGE_SEQUENCE_NOP); | 4540 nop(Assembler::CODE_AGE_SEQUENCE_NOP); |
| 4652 // Adjust fp to point to caller's fp. | 4541 // Adjust fp to point to caller's fp. |
| 4653 Addu(fp, sp, Operand(2 * kPointerSize)); | 4542 Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
| 4654 } | 4543 } |
| 4655 } | 4544 } |
| 4656 } | 4545 } |
| 4657 | 4546 |
| 4658 | 4547 |
| 4659 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 4548 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
| 4660 addiu(sp, sp, -5 * kPointerSize); | 4549 addiu(sp, sp, -5 * kPointerSize); |
| 4661 li(t8, Operand(Smi::FromInt(type))); | 4550 li(t8, Operand(Smi::FromInt(type))); |
| 4662 li(t9, Operand(CodeObject()), CONSTANT_SIZE); | 4551 li(t9, Operand(CodeObject()), CONSTANT_SIZE); |
| 4663 sw(ra, MemOperand(sp, 4 * kPointerSize)); | 4552 sw(ra, MemOperand(sp, 4 * kPointerSize)); |
| 4664 sw(fp, MemOperand(sp, 3 * kPointerSize)); | 4553 sw(fp, MemOperand(sp, 3 * kPointerSize)); |
| 4665 sw(cp, MemOperand(sp, 2 * kPointerSize)); | 4554 sw(cp, MemOperand(sp, 2 * kPointerSize)); |
| 4666 sw(t8, MemOperand(sp, 1 * kPointerSize)); | 4555 sw(t8, MemOperand(sp, 1 * kPointerSize)); |
| 4667 sw(t9, MemOperand(sp, 0 * kPointerSize)); | 4556 sw(t9, MemOperand(sp, 0 * kPointerSize)); |
| 4668 addiu(fp, sp, 3 * kPointerSize); | 4557 // Adjust FP to point to saved FP. |
| 4558 Addu(fp, sp, |
| 4559 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); |
| 4669 } | 4560 } |
| 4670 | 4561 |
| 4671 | 4562 |
| 4672 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 4563 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
| 4673 mov(sp, fp); | 4564 mov(sp, fp); |
| 4674 lw(fp, MemOperand(sp, 0 * kPointerSize)); | 4565 lw(fp, MemOperand(sp, 0 * kPointerSize)); |
| 4675 lw(ra, MemOperand(sp, 1 * kPointerSize)); | 4566 lw(ra, MemOperand(sp, 1 * kPointerSize)); |
| 4676 addiu(sp, sp, 2 * kPointerSize); | 4567 addiu(sp, sp, 2 * kPointerSize); |
| 4677 } | 4568 } |
| 4678 | 4569 |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4947 STATIC_ASSERT(kSmiTag == 0); | 4838 STATIC_ASSERT(kSmiTag == 0); |
| 4948 andi(at, object, kSmiTagMask); | 4839 andi(at, object, kSmiTagMask); |
| 4949 Check(eq, kOperandIsASmi, at, Operand(zero_reg)); | 4840 Check(eq, kOperandIsASmi, at, Operand(zero_reg)); |
| 4950 } | 4841 } |
| 4951 } | 4842 } |
| 4952 | 4843 |
| 4953 | 4844 |
| 4954 void MacroAssembler::AssertString(Register object) { | 4845 void MacroAssembler::AssertString(Register object) { |
| 4955 if (emit_debug_code()) { | 4846 if (emit_debug_code()) { |
| 4956 STATIC_ASSERT(kSmiTag == 0); | 4847 STATIC_ASSERT(kSmiTag == 0); |
| 4957 And(t0, object, Operand(kSmiTagMask)); | 4848 SmiTst(object, t0); |
| 4958 Check(ne, kOperandIsASmiAndNotAString, t0, Operand(zero_reg)); | 4849 Check(ne, kOperandIsASmiAndNotAString, t0, Operand(zero_reg)); |
| 4959 push(object); | 4850 push(object); |
| 4960 lw(object, FieldMemOperand(object, HeapObject::kMapOffset)); | 4851 lw(object, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 4961 lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset)); | 4852 lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset)); |
| 4962 Check(lo, kOperandIsNotAString, object, Operand(FIRST_NONSTRING_TYPE)); | 4853 Check(lo, kOperandIsNotAString, object, Operand(FIRST_NONSTRING_TYPE)); |
| 4963 pop(object); | 4854 pop(object); |
| 4964 } | 4855 } |
| 4965 } | 4856 } |
| 4966 | 4857 |
| 4967 | 4858 |
| 4968 void MacroAssembler::AssertName(Register object) { | 4859 void MacroAssembler::AssertName(Register object) { |
| 4969 if (emit_debug_code()) { | 4860 if (emit_debug_code()) { |
| 4970 STATIC_ASSERT(kSmiTag == 0); | 4861 STATIC_ASSERT(kSmiTag == 0); |
| 4971 And(t0, object, Operand(kSmiTagMask)); | 4862 SmiTst(object, t0); |
| 4972 Check(ne, kOperandIsASmiAndNotAName, t0, Operand(zero_reg)); | 4863 Check(ne, kOperandIsASmiAndNotAName, t0, Operand(zero_reg)); |
| 4973 push(object); | 4864 push(object); |
| 4974 lw(object, FieldMemOperand(object, HeapObject::kMapOffset)); | 4865 lw(object, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 4975 lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset)); | 4866 lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset)); |
| 4976 Check(le, kOperandIsNotAName, object, Operand(LAST_NAME_TYPE)); | 4867 Check(le, kOperandIsNotAName, object, Operand(LAST_NAME_TYPE)); |
| 4977 pop(object); | 4868 pop(object); |
| 4978 } | 4869 } |
| 4979 } | 4870 } |
| 4980 | 4871 |
| 4981 | 4872 |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5155 | 5046 |
| 5156 // Up to four simple arguments are passed in registers a0..a3. | 5047 // Up to four simple arguments are passed in registers a0..a3. |
| 5157 if (num_reg_arguments > kRegisterPassedArguments) { | 5048 if (num_reg_arguments > kRegisterPassedArguments) { |
| 5158 stack_passed_words += num_reg_arguments - kRegisterPassedArguments; | 5049 stack_passed_words += num_reg_arguments - kRegisterPassedArguments; |
| 5159 } | 5050 } |
| 5160 stack_passed_words += kCArgSlotCount; | 5051 stack_passed_words += kCArgSlotCount; |
| 5161 return stack_passed_words; | 5052 return stack_passed_words; |
| 5162 } | 5053 } |
| 5163 | 5054 |
| 5164 | 5055 |
| 5056 void MacroAssembler::EmitSeqStringSetCharCheck(Register string, |
| 5057 Register index, |
| 5058 Register value, |
| 5059 Register scratch, |
| 5060 uint32_t encoding_mask) { |
| 5061 Label is_object; |
| 5062 SmiTst(string, at); |
| 5063 ThrowIf(eq, kNonObject, at, Operand(zero_reg)); |
| 5064 |
| 5065 lw(at, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 5066 lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset)); |
| 5067 |
| 5068 andi(at, at, kStringRepresentationMask | kStringEncodingMask); |
| 5069 li(scratch, Operand(encoding_mask)); |
| 5070 ThrowIf(ne, kUnexpectedStringType, at, Operand(scratch)); |
| 5071 |
| 5072 // The index is assumed to be untagged coming in, tag it to compare with the |
| 5073 // string length without using a temp register, it is restored at the end of |
| 5074 // this function. |
| 5075 Label index_tag_ok, index_tag_bad; |
| 5076 TrySmiTag(index, scratch, &index_tag_bad); |
| 5077 Branch(&index_tag_ok); |
| 5078 bind(&index_tag_bad); |
| 5079 Throw(kIndexIsTooLarge); |
| 5080 bind(&index_tag_ok); |
| 5081 |
| 5082 lw(at, FieldMemOperand(string, String::kLengthOffset)); |
| 5083 ThrowIf(ge, kIndexIsTooLarge, index, Operand(at)); |
| 5084 |
| 5085 ASSERT(Smi::FromInt(0) == 0); |
| 5086 ThrowIf(lt, kIndexIsNegative, index, Operand(zero_reg)); |
| 5087 |
| 5088 SmiUntag(index, index); |
| 5089 } |
| 5090 |
| 5091 |
| 5165 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, | 5092 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
| 5166 int num_double_arguments, | 5093 int num_double_arguments, |
| 5167 Register scratch) { | 5094 Register scratch) { |
| 5168 int frame_alignment = ActivationFrameAlignment(); | 5095 int frame_alignment = ActivationFrameAlignment(); |
| 5169 | 5096 |
| 5170 // Up to four simple arguments are passed in registers a0..a3. | 5097 // Up to four simple arguments are passed in registers a0..a3. |
| 5171 // Those four arguments must have reserved argument slots on the stack for | 5098 // Those four arguments must have reserved argument slots on the stack for |
| 5172 // mips, even though those argument slots are not normally used. | 5099 // mips, even though those argument slots are not normally used. |
| 5173 // Remaining arguments are pushed on the stack, above (higher address than) | 5100 // Remaining arguments are pushed on the stack, above (higher address than) |
| 5174 // the argument slots. | 5101 // the argument slots. |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5535 | 5462 |
| 5536 And(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask)); | 5463 And(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask)); |
| 5537 lw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); | 5464 lw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); |
| 5538 Addu(t8, t8, Operand(length)); | 5465 Addu(t8, t8, Operand(length)); |
| 5539 sw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); | 5466 sw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); |
| 5540 | 5467 |
| 5541 bind(&done); | 5468 bind(&done); |
| 5542 } | 5469 } |
| 5543 | 5470 |
| 5544 | 5471 |
| 5472 void MacroAssembler::Throw(BailoutReason reason) { |
| 5473 Label throw_start; |
| 5474 bind(&throw_start); |
| 5475 #ifdef DEBUG |
| 5476 const char* msg = GetBailoutReason(reason); |
| 5477 if (msg != NULL) { |
| 5478 RecordComment("Throw message: "); |
| 5479 RecordComment(msg); |
| 5480 } |
| 5481 #endif |
| 5482 |
| 5483 li(a0, Operand(Smi::FromInt(reason))); |
| 5484 push(a0); |
| 5485 // Disable stub call restrictions to always allow calls to throw. |
| 5486 if (!has_frame_) { |
| 5487 // We don't actually want to generate a pile of code for this, so just |
| 5488 // claim there is a stack frame, without generating one. |
| 5489 FrameScope scope(this, StackFrame::NONE); |
| 5490 CallRuntime(Runtime::kThrowMessage, 1); |
| 5491 } else { |
| 5492 CallRuntime(Runtime::kThrowMessage, 1); |
| 5493 } |
| 5494 // will not return here |
| 5495 if (is_trampoline_pool_blocked()) { |
| 5496 // If the calling code cares throw the exact number of |
| 5497 // instructions generated, we insert padding here to keep the size |
| 5498 // of the ThrowMessage macro constant. |
| 5499 // Currently in debug mode with debug_code enabled the number of |
| 5500 // generated instructions is 14, so we use this as a maximum value. |
| 5501 static const int kExpectedThrowMessageInstructions = 14; |
| 5502 int throw_instructions = InstructionsGeneratedSince(&throw_start); |
| 5503 ASSERT(throw_instructions <= kExpectedThrowMessageInstructions); |
| 5504 while (throw_instructions++ < kExpectedThrowMessageInstructions) { |
| 5505 nop(); |
| 5506 } |
| 5507 } |
| 5508 } |
| 5509 |
| 5510 |
| 5511 void MacroAssembler::ThrowIf(Condition cc, |
| 5512 BailoutReason reason, |
| 5513 Register rs, |
| 5514 Operand rt) { |
| 5515 Label L; |
| 5516 Branch(&L, NegateCondition(cc), rs, rt); |
| 5517 Throw(reason); |
| 5518 // will not return here |
| 5519 bind(&L); |
| 5520 } |
| 5521 |
| 5522 |
| 5545 void MacroAssembler::LoadInstanceDescriptors(Register map, | 5523 void MacroAssembler::LoadInstanceDescriptors(Register map, |
| 5546 Register descriptors) { | 5524 Register descriptors) { |
| 5547 lw(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); | 5525 lw(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); |
| 5548 } | 5526 } |
| 5549 | 5527 |
| 5550 | 5528 |
| 5551 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { | 5529 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { |
| 5552 lw(dst, FieldMemOperand(map, Map::kBitField3Offset)); | 5530 lw(dst, FieldMemOperand(map, Map::kBitField3Offset)); |
| 5553 DecodeField<Map::NumberOfOwnDescriptorsBits>(dst); | 5531 DecodeField<Map::NumberOfOwnDescriptorsBits>(dst); |
| 5554 } | 5532 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5565 Register empty_fixed_array_value = t2; | 5543 Register empty_fixed_array_value = t2; |
| 5566 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); | 5544 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); |
| 5567 Label next, start; | 5545 Label next, start; |
| 5568 mov(a2, a0); | 5546 mov(a2, a0); |
| 5569 | 5547 |
| 5570 // Check if the enum length field is properly initialized, indicating that | 5548 // Check if the enum length field is properly initialized, indicating that |
| 5571 // there is an enum cache. | 5549 // there is an enum cache. |
| 5572 lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset)); | 5550 lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset)); |
| 5573 | 5551 |
| 5574 EnumLength(a3, a1); | 5552 EnumLength(a3, a1); |
| 5575 Branch(call_runtime, eq, a3, Operand(Smi::FromInt(Map::kInvalidEnumCache))); | 5553 Branch( |
| 5554 call_runtime, eq, a3, Operand(Smi::FromInt(kInvalidEnumCacheSentinel))); |
| 5576 | 5555 |
| 5577 jmp(&start); | 5556 jmp(&start); |
| 5578 | 5557 |
| 5579 bind(&next); | 5558 bind(&next); |
| 5580 lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset)); | 5559 lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset)); |
| 5581 | 5560 |
| 5582 // For all objects but the receiver, check that the cache is empty. | 5561 // For all objects but the receiver, check that the cache is empty. |
| 5583 EnumLength(a3, a1); | 5562 EnumLength(a3, a1); |
| 5584 Branch(call_runtime, ne, a3, Operand(Smi::FromInt(0))); | 5563 Branch(call_runtime, ne, a3, Operand(Smi::FromInt(0))); |
| 5585 | 5564 |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5770 opcode == BGTZL); | 5749 opcode == BGTZL); |
| 5771 opcode = (cond == eq) ? BEQ : BNE; | 5750 opcode = (cond == eq) ? BEQ : BNE; |
| 5772 instr = (instr & ~kOpcodeMask) | opcode; | 5751 instr = (instr & ~kOpcodeMask) | opcode; |
| 5773 masm_.emit(instr); | 5752 masm_.emit(instr); |
| 5774 } | 5753 } |
| 5775 | 5754 |
| 5776 | 5755 |
| 5777 } } // namespace v8::internal | 5756 } } // namespace v8::internal |
| 5778 | 5757 |
| 5779 #endif // V8_TARGET_ARCH_MIPS | 5758 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |