| 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 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 __ li(a2, Operand(Smi::FromInt(length))); | 513 __ li(a2, Operand(Smi::FromInt(length))); |
| 514 __ sw(a2, FieldMemOperand(v0, FixedArray::kLengthOffset)); | 514 __ sw(a2, FieldMemOperand(v0, FixedArray::kLengthOffset)); |
| 515 | 515 |
| 516 // If this block context is nested in the native context we get a smi | 516 // If this block context is nested in the native context we get a smi |
| 517 // sentinel instead of a function. The block context should get the | 517 // sentinel instead of a function. The block context should get the |
| 518 // canonical empty function of the native context as its closure which | 518 // canonical empty function of the native context as its closure which |
| 519 // we still have to look up. | 519 // we still have to look up. |
| 520 Label after_sentinel; | 520 Label after_sentinel; |
| 521 __ JumpIfNotSmi(a3, &after_sentinel); | 521 __ JumpIfNotSmi(a3, &after_sentinel); |
| 522 if (FLAG_debug_code) { | 522 if (FLAG_debug_code) { |
| 523 const char* message = "Expected 0 as a Smi sentinel"; | 523 __ Assert(eq, kExpected0AsASmiSentinel, a3, Operand(zero_reg)); |
| 524 __ Assert(eq, message, a3, Operand(zero_reg)); | |
| 525 } | 524 } |
| 526 __ lw(a3, GlobalObjectOperand()); | 525 __ lw(a3, GlobalObjectOperand()); |
| 527 __ lw(a3, FieldMemOperand(a3, GlobalObject::kNativeContextOffset)); | 526 __ lw(a3, FieldMemOperand(a3, GlobalObject::kNativeContextOffset)); |
| 528 __ lw(a3, ContextOperand(a3, Context::CLOSURE_INDEX)); | 527 __ lw(a3, ContextOperand(a3, Context::CLOSURE_INDEX)); |
| 529 __ bind(&after_sentinel); | 528 __ bind(&after_sentinel); |
| 530 | 529 |
| 531 // Set up the fixed slots, copy the global object from the previous context. | 530 // Set up the fixed slots, copy the global object from the previous context. |
| 532 __ lw(a2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | 531 __ lw(a2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); |
| 533 __ sw(a3, ContextOperand(v0, Context::CLOSURE_INDEX)); | 532 __ sw(a3, ContextOperand(v0, Context::CLOSURE_INDEX)); |
| 534 __ sw(cp, ContextOperand(v0, Context::PREVIOUS_INDEX)); | 533 __ sw(cp, ContextOperand(v0, Context::PREVIOUS_INDEX)); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 Register object, | 671 Register object, |
| 673 FPURegister dst, | 672 FPURegister dst, |
| 674 Register dst1, | 673 Register dst1, |
| 675 Register dst2, | 674 Register dst2, |
| 676 Register heap_number_map, | 675 Register heap_number_map, |
| 677 Register scratch1, | 676 Register scratch1, |
| 678 Register scratch2, | 677 Register scratch2, |
| 679 Label* not_number) { | 678 Label* not_number) { |
| 680 __ AssertRootValue(heap_number_map, | 679 __ AssertRootValue(heap_number_map, |
| 681 Heap::kHeapNumberMapRootIndex, | 680 Heap::kHeapNumberMapRootIndex, |
| 682 "HeapNumberMap register clobbered."); | 681 kHeapNumberMapRegisterClobbered); |
| 683 | 682 |
| 684 Label is_smi, done; | 683 Label is_smi, done; |
| 685 | 684 |
| 686 // Smi-check | 685 // Smi-check |
| 687 __ UntagAndJumpIfSmi(scratch1, object, &is_smi); | 686 __ UntagAndJumpIfSmi(scratch1, object, &is_smi); |
| 688 // Heap number check | 687 // Heap number check |
| 689 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); | 688 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); |
| 690 | 689 |
| 691 // Handle loading a double from a heap number. | 690 // Handle loading a double from a heap number. |
| 692 if (destination == kFPURegisters) { | 691 if (destination == kFPURegisters) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 722 Register object, | 721 Register object, |
| 723 Register dst, | 722 Register dst, |
| 724 Register heap_number_map, | 723 Register heap_number_map, |
| 725 Register scratch1, | 724 Register scratch1, |
| 726 Register scratch2, | 725 Register scratch2, |
| 727 Register scratch3, | 726 Register scratch3, |
| 728 FPURegister double_scratch, | 727 FPURegister double_scratch, |
| 729 Label* not_number) { | 728 Label* not_number) { |
| 730 __ AssertRootValue(heap_number_map, | 729 __ AssertRootValue(heap_number_map, |
| 731 Heap::kHeapNumberMapRootIndex, | 730 Heap::kHeapNumberMapRootIndex, |
| 732 "HeapNumberMap register clobbered."); | 731 kHeapNumberMapRegisterClobbered); |
| 733 Label done; | 732 Label done; |
| 734 Label not_in_int32_range; | 733 Label not_in_int32_range; |
| 735 | 734 |
| 736 __ UntagAndJumpIfSmi(dst, object, &done); | 735 __ UntagAndJumpIfSmi(dst, object, &done); |
| 737 __ lw(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset)); | 736 __ lw(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset)); |
| 738 __ Branch(not_number, ne, scratch1, Operand(heap_number_map)); | 737 __ Branch(not_number, ne, scratch1, Operand(heap_number_map)); |
| 739 __ ConvertToInt32(object, | 738 __ ConvertToInt32(object, |
| 740 dst, | 739 dst, |
| 741 scratch1, | 740 scratch1, |
| 742 scratch2, | 741 scratch2, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 799 | 798 |
| 800 __ JumpIfNotSmi(object, &obj_is_not_smi); | 799 __ JumpIfNotSmi(object, &obj_is_not_smi); |
| 801 __ SmiUntag(scratch1, object); | 800 __ SmiUntag(scratch1, object); |
| 802 ConvertIntToDouble(masm, scratch1, destination, double_dst, dst_mantissa, | 801 ConvertIntToDouble(masm, scratch1, destination, double_dst, dst_mantissa, |
| 803 dst_exponent, scratch2, single_scratch); | 802 dst_exponent, scratch2, single_scratch); |
| 804 __ Branch(&done); | 803 __ Branch(&done); |
| 805 | 804 |
| 806 __ bind(&obj_is_not_smi); | 805 __ bind(&obj_is_not_smi); |
| 807 __ AssertRootValue(heap_number_map, | 806 __ AssertRootValue(heap_number_map, |
| 808 Heap::kHeapNumberMapRootIndex, | 807 Heap::kHeapNumberMapRootIndex, |
| 809 "HeapNumberMap register clobbered."); | 808 kHeapNumberMapRegisterClobbered); |
| 810 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); | 809 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); |
| 811 | 810 |
| 812 // Load the number. | 811 // Load the number. |
| 813 // Load the double value. | 812 // Load the double value. |
| 814 __ ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset)); | 813 __ ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 815 | 814 |
| 816 Register except_flag = scratch2; | 815 Register except_flag = scratch2; |
| 817 __ EmitFPUTruncate(kRoundToZero, | 816 __ EmitFPUTruncate(kRoundToZero, |
| 818 scratch1, | 817 scratch1, |
| 819 double_dst, | 818 double_dst, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 846 ASSERT(!scratch1.is(scratch2) && | 845 ASSERT(!scratch1.is(scratch2) && |
| 847 !scratch1.is(scratch3) && | 846 !scratch1.is(scratch3) && |
| 848 !scratch2.is(scratch3)); | 847 !scratch2.is(scratch3)); |
| 849 | 848 |
| 850 Label done, maybe_undefined; | 849 Label done, maybe_undefined; |
| 851 | 850 |
| 852 __ UntagAndJumpIfSmi(dst, object, &done); | 851 __ UntagAndJumpIfSmi(dst, object, &done); |
| 853 | 852 |
| 854 __ AssertRootValue(heap_number_map, | 853 __ AssertRootValue(heap_number_map, |
| 855 Heap::kHeapNumberMapRootIndex, | 854 Heap::kHeapNumberMapRootIndex, |
| 856 "HeapNumberMap register clobbered."); | 855 kHeapNumberMapRegisterClobbered); |
| 857 | 856 |
| 858 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined); | 857 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined); |
| 859 | 858 |
| 860 // Object is a heap number. | 859 // Object is a heap number. |
| 861 // Convert the floating point value to a 32-bit integer. | 860 // Convert the floating point value to a 32-bit integer. |
| 862 // Load the double value. | 861 // Load the double value. |
| 863 __ ldc1(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset)); | 862 __ ldc1(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 864 | 863 |
| 865 Register except_flag = scratch2; | 864 Register except_flag = scratch2; |
| 866 __ EmitFPUTruncate(kRoundToZero, | 865 __ EmitFPUTruncate(kRoundToZero, |
| (...skipping 3405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4272 STATIC_ASSERT(kSmiTag == 0); | 4271 STATIC_ASSERT(kSmiTag == 0); |
| 4273 __ JumpIfSmi(a0, &runtime); | 4272 __ JumpIfSmi(a0, &runtime); |
| 4274 __ GetObjectType(a0, a1, a1); | 4273 __ GetObjectType(a0, a1, a1); |
| 4275 __ Branch(&runtime, ne, a1, Operand(JS_REGEXP_TYPE)); | 4274 __ Branch(&runtime, ne, a1, Operand(JS_REGEXP_TYPE)); |
| 4276 | 4275 |
| 4277 // Check that the RegExp has been compiled (data contains a fixed array). | 4276 // Check that the RegExp has been compiled (data contains a fixed array). |
| 4278 __ lw(regexp_data, FieldMemOperand(a0, JSRegExp::kDataOffset)); | 4277 __ lw(regexp_data, FieldMemOperand(a0, JSRegExp::kDataOffset)); |
| 4279 if (FLAG_debug_code) { | 4278 if (FLAG_debug_code) { |
| 4280 __ And(t0, regexp_data, Operand(kSmiTagMask)); | 4279 __ And(t0, regexp_data, Operand(kSmiTagMask)); |
| 4281 __ Check(nz, | 4280 __ Check(nz, |
| 4282 "Unexpected type for RegExp data, FixedArray expected", | 4281 kUnexpectedTypeForRegExpDataFixedArrayExpected, |
| 4283 t0, | 4282 t0, |
| 4284 Operand(zero_reg)); | 4283 Operand(zero_reg)); |
| 4285 __ GetObjectType(regexp_data, a0, a0); | 4284 __ GetObjectType(regexp_data, a0, a0); |
| 4286 __ Check(eq, | 4285 __ Check(eq, |
| 4287 "Unexpected type for RegExp data, FixedArray expected", | 4286 kUnexpectedTypeForRegExpDataFixedArrayExpected, |
| 4288 a0, | 4287 a0, |
| 4289 Operand(FIXED_ARRAY_TYPE)); | 4288 Operand(FIXED_ARRAY_TYPE)); |
| 4290 } | 4289 } |
| 4291 | 4290 |
| 4292 // regexp_data: RegExp data (FixedArray) | 4291 // regexp_data: RegExp data (FixedArray) |
| 4293 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. | 4292 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. |
| 4294 __ lw(a0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); | 4293 __ lw(a0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); |
| 4295 __ Branch(&runtime, ne, a0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); | 4294 __ Branch(&runtime, ne, a0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); |
| 4296 | 4295 |
| 4297 // regexp_data: RegExp data (FixedArray) | 4296 // regexp_data: RegExp data (FixedArray) |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4632 | 4631 |
| 4633 // (7) External string. Make it, offset-wise, look like a sequential string. | 4632 // (7) External string. Make it, offset-wise, look like a sequential string. |
| 4634 __ bind(&external_string); | 4633 __ bind(&external_string); |
| 4635 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 4634 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
| 4636 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); | 4635 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); |
| 4637 if (FLAG_debug_code) { | 4636 if (FLAG_debug_code) { |
| 4638 // Assert that we do not have a cons or slice (indirect strings) here. | 4637 // Assert that we do not have a cons or slice (indirect strings) here. |
| 4639 // Sequential strings have already been ruled out. | 4638 // Sequential strings have already been ruled out. |
| 4640 __ And(at, a0, Operand(kIsIndirectStringMask)); | 4639 __ And(at, a0, Operand(kIsIndirectStringMask)); |
| 4641 __ Assert(eq, | 4640 __ Assert(eq, |
| 4642 "external string expected, but not found", | 4641 kExternalStringExpectedButNotFound, |
| 4643 at, | 4642 at, |
| 4644 Operand(zero_reg)); | 4643 Operand(zero_reg)); |
| 4645 } | 4644 } |
| 4646 __ lw(subject, | 4645 __ lw(subject, |
| 4647 FieldMemOperand(subject, ExternalString::kResourceDataOffset)); | 4646 FieldMemOperand(subject, ExternalString::kResourceDataOffset)); |
| 4648 // Move the pointer so that offset-wise, it looks like a sequential string. | 4647 // Move the pointer so that offset-wise, it looks like a sequential string. |
| 4649 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 4648 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
| 4650 __ Subu(subject, | 4649 __ Subu(subject, |
| 4651 subject, | 4650 subject, |
| 4652 SeqTwoByteString::kHeaderSize - kHeapObjectTag); | 4651 SeqTwoByteString::kHeaderSize - kHeapObjectTag); |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5013 &call_runtime_); | 5012 &call_runtime_); |
| 5014 | 5013 |
| 5015 __ sll(result_, result_, kSmiTagSize); | 5014 __ sll(result_, result_, kSmiTagSize); |
| 5016 __ bind(&exit_); | 5015 __ bind(&exit_); |
| 5017 } | 5016 } |
| 5018 | 5017 |
| 5019 | 5018 |
| 5020 void StringCharCodeAtGenerator::GenerateSlow( | 5019 void StringCharCodeAtGenerator::GenerateSlow( |
| 5021 MacroAssembler* masm, | 5020 MacroAssembler* masm, |
| 5022 const RuntimeCallHelper& call_helper) { | 5021 const RuntimeCallHelper& call_helper) { |
| 5023 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); | 5022 __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase); |
| 5024 | 5023 |
| 5025 // Index is not a smi. | 5024 // Index is not a smi. |
| 5026 __ bind(&index_not_smi_); | 5025 __ bind(&index_not_smi_); |
| 5027 // If index is a heap number, try converting it to an integer. | 5026 // If index is a heap number, try converting it to an integer. |
| 5028 __ CheckMap(index_, | 5027 __ CheckMap(index_, |
| 5029 result_, | 5028 result_, |
| 5030 Heap::kHeapNumberMapRootIndex, | 5029 Heap::kHeapNumberMapRootIndex, |
| 5031 index_not_number_, | 5030 index_not_number_, |
| 5032 DONT_DO_SMI_CHECK); | 5031 DONT_DO_SMI_CHECK); |
| 5033 call_helper.BeforeCall(masm); | 5032 call_helper.BeforeCall(masm); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 5062 call_helper.BeforeCall(masm); | 5061 call_helper.BeforeCall(masm); |
| 5063 __ sll(index_, index_, kSmiTagSize); | 5062 __ sll(index_, index_, kSmiTagSize); |
| 5064 __ Push(object_, index_); | 5063 __ Push(object_, index_); |
| 5065 __ CallRuntime(Runtime::kStringCharCodeAt, 2); | 5064 __ CallRuntime(Runtime::kStringCharCodeAt, 2); |
| 5066 | 5065 |
| 5067 __ Move(result_, v0); | 5066 __ Move(result_, v0); |
| 5068 | 5067 |
| 5069 call_helper.AfterCall(masm); | 5068 call_helper.AfterCall(masm); |
| 5070 __ jmp(&exit_); | 5069 __ jmp(&exit_); |
| 5071 | 5070 |
| 5072 __ Abort("Unexpected fallthrough from CharCodeAt slow case"); | 5071 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); |
| 5073 } | 5072 } |
| 5074 | 5073 |
| 5075 | 5074 |
| 5076 // ------------------------------------------------------------------------- | 5075 // ------------------------------------------------------------------------- |
| 5077 // StringCharFromCodeGenerator | 5076 // StringCharFromCodeGenerator |
| 5078 | 5077 |
| 5079 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { | 5078 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { |
| 5080 // Fast case of Heap::LookupSingleCharacterStringFromCode. | 5079 // Fast case of Heap::LookupSingleCharacterStringFromCode. |
| 5081 | 5080 |
| 5082 ASSERT(!t0.is(result_)); | 5081 ASSERT(!t0.is(result_)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 5099 __ lw(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); | 5098 __ lw(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); |
| 5100 __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); | 5099 __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); |
| 5101 __ Branch(&slow_case_, eq, result_, Operand(t0)); | 5100 __ Branch(&slow_case_, eq, result_, Operand(t0)); |
| 5102 __ bind(&exit_); | 5101 __ bind(&exit_); |
| 5103 } | 5102 } |
| 5104 | 5103 |
| 5105 | 5104 |
| 5106 void StringCharFromCodeGenerator::GenerateSlow( | 5105 void StringCharFromCodeGenerator::GenerateSlow( |
| 5107 MacroAssembler* masm, | 5106 MacroAssembler* masm, |
| 5108 const RuntimeCallHelper& call_helper) { | 5107 const RuntimeCallHelper& call_helper) { |
| 5109 __ Abort("Unexpected fallthrough to CharFromCode slow case"); | 5108 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); |
| 5110 | 5109 |
| 5111 __ bind(&slow_case_); | 5110 __ bind(&slow_case_); |
| 5112 call_helper.BeforeCall(masm); | 5111 call_helper.BeforeCall(masm); |
| 5113 __ push(code_); | 5112 __ push(code_); |
| 5114 __ CallRuntime(Runtime::kCharFromCode, 1); | 5113 __ CallRuntime(Runtime::kCharFromCode, 1); |
| 5115 __ Move(result_, v0); | 5114 __ Move(result_, v0); |
| 5116 | 5115 |
| 5117 call_helper.AfterCall(masm); | 5116 call_helper.AfterCall(masm); |
| 5118 __ Branch(&exit_); | 5117 __ Branch(&exit_); |
| 5119 | 5118 |
| 5120 __ Abort("Unexpected fallthrough from CharFromCode slow case"); | 5119 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); |
| 5121 } | 5120 } |
| 5122 | 5121 |
| 5123 | 5122 |
| 5124 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, | 5123 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, |
| 5125 Register dest, | 5124 Register dest, |
| 5126 Register src, | 5125 Register src, |
| 5127 Register count, | 5126 Register count, |
| 5128 Register scratch, | 5127 Register scratch, |
| 5129 bool ascii) { | 5128 bool ascii) { |
| 5130 Label loop; | 5129 Label loop; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5165 Register scratch5, | 5164 Register scratch5, |
| 5166 int flags) { | 5165 int flags) { |
| 5167 bool ascii = (flags & COPY_ASCII) != 0; | 5166 bool ascii = (flags & COPY_ASCII) != 0; |
| 5168 bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0; | 5167 bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0; |
| 5169 | 5168 |
| 5170 if (dest_always_aligned && FLAG_debug_code) { | 5169 if (dest_always_aligned && FLAG_debug_code) { |
| 5171 // Check that destination is actually word aligned if the flag says | 5170 // Check that destination is actually word aligned if the flag says |
| 5172 // that it is. | 5171 // that it is. |
| 5173 __ And(scratch4, dest, Operand(kPointerAlignmentMask)); | 5172 __ And(scratch4, dest, Operand(kPointerAlignmentMask)); |
| 5174 __ Check(eq, | 5173 __ Check(eq, |
| 5175 "Destination of copy not aligned.", | 5174 kDestinationOfCopyNotAligned, |
| 5176 scratch4, | 5175 scratch4, |
| 5177 Operand(zero_reg)); | 5176 Operand(zero_reg)); |
| 5178 } | 5177 } |
| 5179 | 5178 |
| 5180 const int kReadAlignment = 4; | 5179 const int kReadAlignment = 4; |
| 5181 const int kReadAlignmentMask = kReadAlignment - 1; | 5180 const int kReadAlignmentMask = kReadAlignment - 1; |
| 5182 // Ensure that reading an entire aligned word containing the last character | 5181 // Ensure that reading an entire aligned word containing the last character |
| 5183 // of a string will not read outside the allocated area (because we pad up | 5182 // of a string will not read outside the allocated area (because we pad up |
| 5184 // to kObjectAlignment). | 5183 // to kObjectAlignment). |
| 5185 STATIC_ASSERT(kObjectAlignment >= kReadAlignment); | 5184 STATIC_ASSERT(kObjectAlignment >= kReadAlignment); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5365 | 5364 |
| 5366 // If entry is undefined no string with this hash can be found. | 5365 // If entry is undefined no string with this hash can be found. |
| 5367 Label is_string; | 5366 Label is_string; |
| 5368 __ GetObjectType(candidate, scratch, scratch); | 5367 __ GetObjectType(candidate, scratch, scratch); |
| 5369 __ Branch(&is_string, ne, scratch, Operand(ODDBALL_TYPE)); | 5368 __ Branch(&is_string, ne, scratch, Operand(ODDBALL_TYPE)); |
| 5370 | 5369 |
| 5371 __ Branch(not_found, eq, undefined, Operand(candidate)); | 5370 __ Branch(not_found, eq, undefined, Operand(candidate)); |
| 5372 // Must be the hole (deleted entry). | 5371 // Must be the hole (deleted entry). |
| 5373 if (FLAG_debug_code) { | 5372 if (FLAG_debug_code) { |
| 5374 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | 5373 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
| 5375 __ Assert(eq, "oddball in string table is not undefined or the hole", | 5374 __ Assert(eq, kOddballInStringTableIsNotUndefinedOrTheHole, |
| 5376 scratch, Operand(candidate)); | 5375 scratch, Operand(candidate)); |
| 5377 } | 5376 } |
| 5378 __ jmp(&next_probe[i]); | 5377 __ jmp(&next_probe[i]); |
| 5379 | 5378 |
| 5380 __ bind(&is_string); | 5379 __ bind(&is_string); |
| 5381 | 5380 |
| 5382 // Check that the candidate is a non-external ASCII string. The instance | 5381 // Check that the candidate is a non-external ASCII string. The instance |
| 5383 // type is still in the scratch register from the CompareObjectType | 5382 // type is still in the scratch register from the CompareObjectType |
| 5384 // operation. | 5383 // operation. |
| 5385 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]); | 5384 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]); |
| (...skipping 1187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6573 // No need to pop or drop anything, LeaveExitFrame will restore the old | 6572 // No need to pop or drop anything, LeaveExitFrame will restore the old |
| 6574 // stack, thus dropping the allocated space for the return value. | 6573 // stack, thus dropping the allocated space for the return value. |
| 6575 // The saved ra is after the reserved stack space for the 4 args. | 6574 // The saved ra is after the reserved stack space for the 4 args. |
| 6576 __ lw(t9, MemOperand(sp, kCArgsSlotsSize)); | 6575 __ lw(t9, MemOperand(sp, kCArgsSlotsSize)); |
| 6577 | 6576 |
| 6578 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 6577 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
| 6579 // In case of an error the return address may point to a memory area | 6578 // In case of an error the return address may point to a memory area |
| 6580 // filled with kZapValue by the GC. | 6579 // filled with kZapValue by the GC. |
| 6581 // Dereference the address and check for this. | 6580 // Dereference the address and check for this. |
| 6582 __ lw(t0, MemOperand(t9)); | 6581 __ lw(t0, MemOperand(t9)); |
| 6583 __ Assert(ne, "Received invalid return address.", t0, | 6582 __ Assert(ne, kReceivedInvalidReturnAddress, t0, |
| 6584 Operand(reinterpret_cast<uint32_t>(kZapValue))); | 6583 Operand(reinterpret_cast<uint32_t>(kZapValue))); |
| 6585 } | 6584 } |
| 6586 __ Jump(t9); | 6585 __ Jump(t9); |
| 6587 } | 6586 } |
| 6588 | 6587 |
| 6589 | 6588 |
| 6590 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, | 6589 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, |
| 6591 Register target) { | 6590 Register target) { |
| 6592 __ Move(t9, target); | 6591 __ Move(t9, target); |
| 6593 __ AssertStackIsAligned(); | 6592 __ AssertStackIsAligned(); |
| (...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7324 for (int i = 0; i <= last_index; ++i) { | 7323 for (int i = 0; i <= last_index; ++i) { |
| 7325 Label next; | 7324 Label next; |
| 7326 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7325 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7327 __ Branch(&next, ne, a3, Operand(kind)); | 7326 __ Branch(&next, ne, a3, Operand(kind)); |
| 7328 T stub(kind); | 7327 T stub(kind); |
| 7329 __ TailCallStub(&stub); | 7328 __ TailCallStub(&stub); |
| 7330 __ bind(&next); | 7329 __ bind(&next); |
| 7331 } | 7330 } |
| 7332 | 7331 |
| 7333 // If we reached this point there is a problem. | 7332 // If we reached this point there is a problem. |
| 7334 __ Abort("Unexpected ElementsKind in array constructor"); | 7333 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
| 7335 } | 7334 } |
| 7336 | 7335 |
| 7337 | 7336 |
| 7338 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) { | 7337 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) { |
| 7339 // a2 - type info cell | 7338 // a2 - type info cell |
| 7340 // a3 - kind | 7339 // a3 - kind |
| 7341 // a0 - number of arguments | 7340 // a0 - number of arguments |
| 7342 // a1 - constructor? | 7341 // a1 - constructor? |
| 7343 // sp[0] - last argument | 7342 // sp[0] - last argument |
| 7344 ASSERT(FAST_SMI_ELEMENTS == 0); | 7343 ASSERT(FAST_SMI_ELEMENTS == 0); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7379 for (int i = 0; i <= last_index; ++i) { | 7378 for (int i = 0; i <= last_index; ++i) { |
| 7380 Label next; | 7379 Label next; |
| 7381 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7380 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7382 __ Branch(&next, ne, a3, Operand(kind)); | 7381 __ Branch(&next, ne, a3, Operand(kind)); |
| 7383 ArraySingleArgumentConstructorStub stub(kind); | 7382 ArraySingleArgumentConstructorStub stub(kind); |
| 7384 __ TailCallStub(&stub); | 7383 __ TailCallStub(&stub); |
| 7385 __ bind(&next); | 7384 __ bind(&next); |
| 7386 } | 7385 } |
| 7387 | 7386 |
| 7388 // If we reached this point there is a problem. | 7387 // If we reached this point there is a problem. |
| 7389 __ Abort("Unexpected ElementsKind in array constructor"); | 7388 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
| 7390 } | 7389 } |
| 7391 | 7390 |
| 7392 | 7391 |
| 7393 template<class T> | 7392 template<class T> |
| 7394 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | 7393 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { |
| 7395 int to_index = GetSequenceIndexFromFastElementsKind( | 7394 int to_index = GetSequenceIndexFromFastElementsKind( |
| 7396 TERMINAL_FAST_ELEMENTS_KIND); | 7395 TERMINAL_FAST_ELEMENTS_KIND); |
| 7397 for (int i = 0; i <= to_index; ++i) { | 7396 for (int i = 0; i <= to_index; ++i) { |
| 7398 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7397 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7399 T stub(kind); | 7398 T stub(kind); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7440 // -- sp[4] : last argument | 7439 // -- sp[4] : last argument |
| 7441 // ----------------------------------- | 7440 // ----------------------------------- |
| 7442 if (FLAG_debug_code) { | 7441 if (FLAG_debug_code) { |
| 7443 // The array construct code is only set for the global and natives | 7442 // The array construct code is only set for the global and natives |
| 7444 // builtin Array functions which always have maps. | 7443 // builtin Array functions which always have maps. |
| 7445 | 7444 |
| 7446 // Initial map for the builtin Array function should be a map. | 7445 // Initial map for the builtin Array function should be a map. |
| 7447 __ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); | 7446 __ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); |
| 7448 // Will both indicate a NULL and a Smi. | 7447 // Will both indicate a NULL and a Smi. |
| 7449 __ And(at, a3, Operand(kSmiTagMask)); | 7448 __ And(at, a3, Operand(kSmiTagMask)); |
| 7450 __ Assert(ne, "Unexpected initial map for Array function", | 7449 __ Assert(ne, kUnexpectedInitialMapForArrayFunction, |
| 7451 at, Operand(zero_reg)); | 7450 at, Operand(zero_reg)); |
| 7452 __ GetObjectType(a3, a3, t0); | 7451 __ GetObjectType(a3, a3, t0); |
| 7453 __ Assert(eq, "Unexpected initial map for Array function", | 7452 __ Assert(eq, kUnexpectedInitialMapForArrayFunction, |
| 7454 t0, Operand(MAP_TYPE)); | 7453 t0, Operand(MAP_TYPE)); |
| 7455 | 7454 |
| 7456 // We should either have undefined in a2 or a valid cell. | 7455 // We should either have undefined in a2 or a valid cell. |
| 7457 Label okay_here; | 7456 Label okay_here; |
| 7458 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); | 7457 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); |
| 7459 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 7458 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 7460 __ Branch(&okay_here, eq, a2, Operand(at)); | 7459 __ Branch(&okay_here, eq, a2, Operand(at)); |
| 7461 __ lw(a3, FieldMemOperand(a2, 0)); | 7460 __ lw(a3, FieldMemOperand(a2, 0)); |
| 7462 __ Assert(eq, "Expected property cell in register a2", | 7461 __ Assert(eq, kExpectedPropertyCellInRegisterA2, |
| 7463 a3, Operand(cell_map)); | 7462 a3, Operand(cell_map)); |
| 7464 __ bind(&okay_here); | 7463 __ bind(&okay_here); |
| 7465 } | 7464 } |
| 7466 | 7465 |
| 7467 Label no_info, switch_ready; | 7466 Label no_info, switch_ready; |
| 7468 // Get the elements kind and case on that. | 7467 // Get the elements kind and case on that. |
| 7469 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 7468 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 7470 __ Branch(&no_info, eq, a2, Operand(at)); | 7469 __ Branch(&no_info, eq, a2, Operand(at)); |
| 7471 __ lw(a3, FieldMemOperand(a2, Cell::kValueOffset)); | 7470 __ lw(a3, FieldMemOperand(a2, Cell::kValueOffset)); |
| 7472 | 7471 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7552 // ----------------------------------- | 7551 // ----------------------------------- |
| 7553 | 7552 |
| 7554 if (FLAG_debug_code) { | 7553 if (FLAG_debug_code) { |
| 7555 // The array construct code is only set for the global and natives | 7554 // The array construct code is only set for the global and natives |
| 7556 // builtin Array functions which always have maps. | 7555 // builtin Array functions which always have maps. |
| 7557 | 7556 |
| 7558 // Initial map for the builtin Array function should be a map. | 7557 // Initial map for the builtin Array function should be a map. |
| 7559 __ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); | 7558 __ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); |
| 7560 // Will both indicate a NULL and a Smi. | 7559 // Will both indicate a NULL and a Smi. |
| 7561 __ And(at, a3, Operand(kSmiTagMask)); | 7560 __ And(at, a3, Operand(kSmiTagMask)); |
| 7562 __ Assert(ne, "Unexpected initial map for Array function", | 7561 __ Assert(ne, kUnexpectedInitialMapForArrayFunction, |
| 7563 at, Operand(zero_reg)); | 7562 at, Operand(zero_reg)); |
| 7564 __ GetObjectType(a3, a3, t0); | 7563 __ GetObjectType(a3, a3, t0); |
| 7565 __ Assert(eq, "Unexpected initial map for Array function", | 7564 __ Assert(eq, kUnexpectedInitialMapForArrayFunction, |
| 7566 t0, Operand(MAP_TYPE)); | 7565 t0, Operand(MAP_TYPE)); |
| 7567 } | 7566 } |
| 7568 | 7567 |
| 7569 // Figure out the right elements kind. | 7568 // Figure out the right elements kind. |
| 7570 __ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); | 7569 __ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); |
| 7571 | 7570 |
| 7572 // Load the map's "bit field 2" into a3. We only need the first byte, | 7571 // Load the map's "bit field 2" into a3. We only need the first byte, |
| 7573 // but the following bit field extraction takes care of that anyway. | 7572 // but the following bit field extraction takes care of that anyway. |
| 7574 __ lbu(a3, FieldMemOperand(a3, Map::kBitField2Offset)); | 7573 __ lbu(a3, FieldMemOperand(a3, Map::kBitField2Offset)); |
| 7575 // Retrieve elements_kind from bit field 2. | 7574 // Retrieve elements_kind from bit field 2. |
| 7576 __ Ext(a3, a3, Map::kElementsKindShift, Map::kElementsKindBitCount); | 7575 __ Ext(a3, a3, Map::kElementsKindShift, Map::kElementsKindBitCount); |
| 7577 | 7576 |
| 7578 if (FLAG_debug_code) { | 7577 if (FLAG_debug_code) { |
| 7579 Label done; | 7578 Label done; |
| 7580 __ Branch(&done, eq, a3, Operand(FAST_ELEMENTS)); | 7579 __ Branch(&done, eq, a3, Operand(FAST_ELEMENTS)); |
| 7581 __ Assert( | 7580 __ Assert( |
| 7582 eq, "Invalid ElementsKind for InternalArray or InternalPackedArray", | 7581 eq, kInvalidElementsKindForInternalArrayOrInternalPackedArray, |
| 7583 a3, Operand(FAST_HOLEY_ELEMENTS)); | 7582 a3, Operand(FAST_HOLEY_ELEMENTS)); |
| 7584 __ bind(&done); | 7583 __ bind(&done); |
| 7585 } | 7584 } |
| 7586 | 7585 |
| 7587 Label fast_elements_case; | 7586 Label fast_elements_case; |
| 7588 __ Branch(&fast_elements_case, eq, a3, Operand(FAST_ELEMENTS)); | 7587 __ Branch(&fast_elements_case, eq, a3, Operand(FAST_ELEMENTS)); |
| 7589 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 7588 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
| 7590 | 7589 |
| 7591 __ bind(&fast_elements_case); | 7590 __ bind(&fast_elements_case); |
| 7592 GenerateCase(masm, FAST_ELEMENTS); | 7591 GenerateCase(masm, FAST_ELEMENTS); |
| 7593 } | 7592 } |
| 7594 | 7593 |
| 7595 | 7594 |
| 7596 #undef __ | 7595 #undef __ |
| 7597 | 7596 |
| 7598 } } // namespace v8::internal | 7597 } } // namespace v8::internal |
| 7599 | 7598 |
| 7600 #endif // V8_TARGET_ARCH_MIPS | 7599 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |