| 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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 __ LoadRoot(r2, Heap::kTheHoleValueRootIndex); | 115 __ LoadRoot(r2, Heap::kTheHoleValueRootIndex); |
| 116 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); | 116 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); |
| 117 __ str(r1, FieldMemOperand(r0, JSObject::kPropertiesOffset)); | 117 __ str(r1, FieldMemOperand(r0, JSObject::kPropertiesOffset)); |
| 118 __ str(r1, FieldMemOperand(r0, JSObject::kElementsOffset)); | 118 __ str(r1, FieldMemOperand(r0, JSObject::kElementsOffset)); |
| 119 __ str(r2, FieldMemOperand(r0, JSFunction::kPrototypeOrInitialMapOffset)); | 119 __ str(r2, FieldMemOperand(r0, JSFunction::kPrototypeOrInitialMapOffset)); |
| 120 __ str(r3, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset)); | 120 __ str(r3, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset)); |
| 121 __ str(cp, FieldMemOperand(r0, JSFunction::kContextOffset)); | 121 __ str(cp, FieldMemOperand(r0, JSFunction::kContextOffset)); |
| 122 __ str(r1, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); | 122 __ str(r1, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); |
| 123 __ str(r4, FieldMemOperand(r0, JSFunction::kNextFunctionLinkOffset)); | 123 __ str(r4, FieldMemOperand(r0, JSFunction::kNextFunctionLinkOffset)); |
| 124 | 124 |
| 125 | |
| 126 // Initialize the code pointer in the function to be the one | 125 // Initialize the code pointer in the function to be the one |
| 127 // found in the shared function info object. | 126 // found in the shared function info object. |
| 128 __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset)); | 127 __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset)); |
| 129 __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); | 128 __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 130 __ str(r3, FieldMemOperand(r0, JSFunction::kCodeEntryOffset)); | 129 __ str(r3, FieldMemOperand(r0, JSFunction::kCodeEntryOffset)); |
| 131 | 130 |
| 132 // Return result. The argument function info has been popped already. | 131 // Return result. The argument function info has been popped already. |
| 133 __ Ret(); | 132 __ Ret(); |
| 134 | 133 |
| 135 // Create a new closure through the slower runtime call. | 134 // Create a new closure through the slower runtime call. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 150 r0, | 149 r0, |
| 151 r1, | 150 r1, |
| 152 r2, | 151 r2, |
| 153 &gc, | 152 &gc, |
| 154 TAG_OBJECT); | 153 TAG_OBJECT); |
| 155 | 154 |
| 156 // Load the function from the stack. | 155 // Load the function from the stack. |
| 157 __ ldr(r3, MemOperand(sp, 0)); | 156 __ ldr(r3, MemOperand(sp, 0)); |
| 158 | 157 |
| 159 // Set up the object header. | 158 // Set up the object header. |
| 160 __ LoadRoot(r2, Heap::kFunctionContextMapRootIndex); | 159 __ LoadRoot(r1, Heap::kFunctionContextMapRootIndex); |
| 161 __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | |
| 162 __ mov(r2, Operand(Smi::FromInt(length))); | 160 __ mov(r2, Operand(Smi::FromInt(length))); |
| 163 __ str(r2, FieldMemOperand(r0, FixedArray::kLengthOffset)); | 161 __ str(r2, FieldMemOperand(r0, FixedArray::kLengthOffset)); |
| 162 __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 164 | 163 |
| 165 // Set up the fixed slots. | 164 // Set up the fixed slots, copy the global object from the previous context. |
| 165 __ ldr(r2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 166 __ mov(r1, Operand(Smi::FromInt(0))); | 166 __ mov(r1, Operand(Smi::FromInt(0))); |
| 167 __ str(r3, MemOperand(r0, Context::SlotOffset(Context::CLOSURE_INDEX))); | 167 __ str(r3, MemOperand(r0, Context::SlotOffset(Context::CLOSURE_INDEX))); |
| 168 __ str(cp, MemOperand(r0, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 168 __ str(cp, MemOperand(r0, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
| 169 __ str(r1, MemOperand(r0, Context::SlotOffset(Context::EXTENSION_INDEX))); | 169 __ str(r1, MemOperand(r0, Context::SlotOffset(Context::EXTENSION_INDEX))); |
| 170 | 170 __ str(r2, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 171 // Copy the global object from the previous context. | |
| 172 __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); | |
| 173 __ str(r1, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_INDEX))); | |
| 174 | 171 |
| 175 // Initialize the rest of the slots to undefined. | 172 // Initialize the rest of the slots to undefined. |
| 176 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); | 173 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
| 177 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { | 174 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { |
| 178 __ str(r1, MemOperand(r0, Context::SlotOffset(i))); | 175 __ str(r1, MemOperand(r0, Context::SlotOffset(i))); |
| 179 } | 176 } |
| 180 | 177 |
| 181 // Remove the on-stack argument and return. | 178 // Remove the on-stack argument and return. |
| 182 __ mov(cp, r0); | 179 __ mov(cp, r0); |
| 183 __ pop(); | 180 __ pop(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 if (FLAG_debug_code) { | 219 if (FLAG_debug_code) { |
| 223 const char* message = "Expected 0 as a Smi sentinel"; | 220 const char* message = "Expected 0 as a Smi sentinel"; |
| 224 __ cmp(r3, Operand::Zero()); | 221 __ cmp(r3, Operand::Zero()); |
| 225 __ Assert(eq, message); | 222 __ Assert(eq, message); |
| 226 } | 223 } |
| 227 __ ldr(r3, GlobalObjectOperand()); | 224 __ ldr(r3, GlobalObjectOperand()); |
| 228 __ ldr(r3, FieldMemOperand(r3, GlobalObject::kGlobalContextOffset)); | 225 __ ldr(r3, FieldMemOperand(r3, GlobalObject::kGlobalContextOffset)); |
| 229 __ ldr(r3, ContextOperand(r3, Context::CLOSURE_INDEX)); | 226 __ ldr(r3, ContextOperand(r3, Context::CLOSURE_INDEX)); |
| 230 __ bind(&after_sentinel); | 227 __ bind(&after_sentinel); |
| 231 | 228 |
| 232 // Set up the fixed slots. | 229 // Set up the fixed slots, copy the global object from the previous context. |
| 230 __ ldr(r2, ContextOperand(cp, Context::GLOBAL_INDEX)); |
| 233 __ str(r3, ContextOperand(r0, Context::CLOSURE_INDEX)); | 231 __ str(r3, ContextOperand(r0, Context::CLOSURE_INDEX)); |
| 234 __ str(cp, ContextOperand(r0, Context::PREVIOUS_INDEX)); | 232 __ str(cp, ContextOperand(r0, Context::PREVIOUS_INDEX)); |
| 235 __ str(r1, ContextOperand(r0, Context::EXTENSION_INDEX)); | 233 __ str(r1, ContextOperand(r0, Context::EXTENSION_INDEX)); |
| 236 | 234 __ str(r2, ContextOperand(r0, Context::GLOBAL_INDEX)); |
| 237 // Copy the global object from the previous context. | |
| 238 __ ldr(r1, ContextOperand(cp, Context::GLOBAL_INDEX)); | |
| 239 __ str(r1, ContextOperand(r0, Context::GLOBAL_INDEX)); | |
| 240 | 235 |
| 241 // Initialize the rest of the slots to the hole value. | 236 // Initialize the rest of the slots to the hole value. |
| 242 __ LoadRoot(r1, Heap::kTheHoleValueRootIndex); | 237 __ LoadRoot(r1, Heap::kTheHoleValueRootIndex); |
| 243 for (int i = 0; i < slots_; i++) { | 238 for (int i = 0; i < slots_; i++) { |
| 244 __ str(r1, ContextOperand(r0, i + Context::MIN_CONTEXT_SLOTS)); | 239 __ str(r1, ContextOperand(r0, i + Context::MIN_CONTEXT_SLOTS)); |
| 245 } | 240 } |
| 246 | 241 |
| 247 // Remove the on-stack argument and return. | 242 // Remove the on-stack argument and return. |
| 248 __ mov(cp, r0); | 243 __ mov(cp, r0); |
| 249 __ add(sp, sp, Operand(2 * kPointerSize)); | 244 __ add(sp, sp, Operand(2 * kPointerSize)); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 __ add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 314 __ add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 320 __ ldr(r3, MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 315 __ ldr(r3, MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 321 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); | 316 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); |
| 322 __ b(eq, &slow_case); | 317 __ b(eq, &slow_case); |
| 323 | 318 |
| 324 FastCloneShallowArrayStub::Mode mode = mode_; | 319 FastCloneShallowArrayStub::Mode mode = mode_; |
| 325 if (mode == CLONE_ANY_ELEMENTS) { | 320 if (mode == CLONE_ANY_ELEMENTS) { |
| 326 Label double_elements, check_fast_elements; | 321 Label double_elements, check_fast_elements; |
| 327 __ ldr(r0, FieldMemOperand(r3, JSArray::kElementsOffset)); | 322 __ ldr(r0, FieldMemOperand(r3, JSArray::kElementsOffset)); |
| 328 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); | 323 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 329 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); | 324 __ CompareRoot(r0, Heap::kFixedCOWArrayMapRootIndex); |
| 330 __ cmp(r0, ip); | |
| 331 __ b(ne, &check_fast_elements); | 325 __ b(ne, &check_fast_elements); |
| 332 GenerateFastCloneShallowArrayCommon(masm, 0, | 326 GenerateFastCloneShallowArrayCommon(masm, 0, |
| 333 COPY_ON_WRITE_ELEMENTS, &slow_case); | 327 COPY_ON_WRITE_ELEMENTS, &slow_case); |
| 334 // Return and remove the on-stack parameters. | 328 // Return and remove the on-stack parameters. |
| 335 __ add(sp, sp, Operand(3 * kPointerSize)); | 329 __ add(sp, sp, Operand(3 * kPointerSize)); |
| 336 __ Ret(); | 330 __ Ret(); |
| 337 | 331 |
| 338 __ bind(&check_fast_elements); | 332 __ bind(&check_fast_elements); |
| 339 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 333 __ CompareRoot(r0, Heap::kFixedArrayMapRootIndex); |
| 340 __ cmp(r0, ip); | |
| 341 __ b(ne, &double_elements); | 334 __ b(ne, &double_elements); |
| 342 GenerateFastCloneShallowArrayCommon(masm, length_, | 335 GenerateFastCloneShallowArrayCommon(masm, length_, |
| 343 CLONE_ELEMENTS, &slow_case); | 336 CLONE_ELEMENTS, &slow_case); |
| 344 // Return and remove the on-stack parameters. | 337 // Return and remove the on-stack parameters. |
| 345 __ add(sp, sp, Operand(3 * kPointerSize)); | 338 __ add(sp, sp, Operand(3 * kPointerSize)); |
| 346 __ Ret(); | 339 __ Ret(); |
| 347 | 340 |
| 348 __ bind(&double_elements); | 341 __ bind(&double_elements); |
| 349 mode = CLONE_DOUBLE_ELEMENTS; | 342 mode = CLONE_DOUBLE_ELEMENTS; |
| 350 // Fall through to generate the code to handle double elements. | 343 // Fall through to generate the code to handle double elements. |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 Register scratch2, | 576 Register scratch2, |
| 584 Label* not_number) { | 577 Label* not_number) { |
| 585 if (FLAG_debug_code) { | 578 if (FLAG_debug_code) { |
| 586 __ AbortIfNotRootValue(heap_number_map, | 579 __ AbortIfNotRootValue(heap_number_map, |
| 587 Heap::kHeapNumberMapRootIndex, | 580 Heap::kHeapNumberMapRootIndex, |
| 588 "HeapNumberMap register clobbered."); | 581 "HeapNumberMap register clobbered."); |
| 589 } | 582 } |
| 590 | 583 |
| 591 Label is_smi, done; | 584 Label is_smi, done; |
| 592 | 585 |
| 593 __ JumpIfSmi(object, &is_smi); | 586 // Smi-check |
| 587 __ UntagAndJumpIfSmi(scratch1, object, &is_smi); |
| 588 // Heap number check |
| 594 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); | 589 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); |
| 595 | 590 |
| 596 // Handle loading a double from a heap number. | 591 // Handle loading a double from a heap number. |
| 597 if (CpuFeatures::IsSupported(VFP3) && | 592 if (CpuFeatures::IsSupported(VFP3) && |
| 598 destination == kVFPRegisters) { | 593 destination == kVFPRegisters) { |
| 599 CpuFeatures::Scope scope(VFP3); | 594 CpuFeatures::Scope scope(VFP3); |
| 600 // Load the double from tagged HeapNumber to double register. | 595 // Load the double from tagged HeapNumber to double register. |
| 601 __ sub(scratch1, object, Operand(kHeapObjectTag)); | 596 __ sub(scratch1, object, Operand(kHeapObjectTag)); |
| 602 __ vldr(dst, scratch1, HeapNumber::kValueOffset); | 597 __ vldr(dst, scratch1, HeapNumber::kValueOffset); |
| 603 } else { | 598 } else { |
| 604 ASSERT(destination == kCoreRegisters); | 599 ASSERT(destination == kCoreRegisters); |
| 605 // Load the double from heap number to dst1 and dst2 in double format. | 600 // Load the double from heap number to dst1 and dst2 in double format. |
| 606 __ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset)); | 601 __ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 607 } | 602 } |
| 608 __ jmp(&done); | 603 __ jmp(&done); |
| 609 | 604 |
| 610 // Handle loading a double from a smi. | 605 // Handle loading a double from a smi. |
| 611 __ bind(&is_smi); | 606 __ bind(&is_smi); |
| 612 if (CpuFeatures::IsSupported(VFP3)) { | 607 if (CpuFeatures::IsSupported(VFP3)) { |
| 613 CpuFeatures::Scope scope(VFP3); | 608 CpuFeatures::Scope scope(VFP3); |
| 614 // Convert smi to double using VFP instructions. | 609 // Convert smi to double using VFP instructions. |
| 615 __ SmiUntag(scratch1, object); | |
| 616 __ vmov(dst.high(), scratch1); | 610 __ vmov(dst.high(), scratch1); |
| 617 __ vcvt_f64_s32(dst, dst.high()); | 611 __ vcvt_f64_s32(dst, dst.high()); |
| 618 if (destination == kCoreRegisters) { | 612 if (destination == kCoreRegisters) { |
| 619 // Load the converted smi to dst1 and dst2 in double format. | 613 // Load the converted smi to dst1 and dst2 in double format. |
| 620 __ vmov(dst1, dst2, dst); | 614 __ vmov(dst1, dst2, dst); |
| 621 } | 615 } |
| 622 } else { | 616 } else { |
| 623 ASSERT(destination == kCoreRegisters); | 617 ASSERT(destination == kCoreRegisters); |
| 624 // Write smi to dst1 and dst2 double format. | 618 // Write smi to dst1 and dst2 double format. |
| 625 __ mov(scratch1, Operand(object)); | 619 __ mov(scratch1, Operand(object)); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 640 Register scratch1, | 634 Register scratch1, |
| 641 Register scratch2, | 635 Register scratch2, |
| 642 Register scratch3, | 636 Register scratch3, |
| 643 DwVfpRegister double_scratch, | 637 DwVfpRegister double_scratch, |
| 644 Label* not_number) { | 638 Label* not_number) { |
| 645 if (FLAG_debug_code) { | 639 if (FLAG_debug_code) { |
| 646 __ AbortIfNotRootValue(heap_number_map, | 640 __ AbortIfNotRootValue(heap_number_map, |
| 647 Heap::kHeapNumberMapRootIndex, | 641 Heap::kHeapNumberMapRootIndex, |
| 648 "HeapNumberMap register clobbered."); | 642 "HeapNumberMap register clobbered."); |
| 649 } | 643 } |
| 650 Label is_smi; | |
| 651 Label done; | 644 Label done; |
| 652 Label not_in_int32_range; | 645 Label not_in_int32_range; |
| 653 | 646 |
| 654 __ JumpIfSmi(object, &is_smi); | 647 __ UntagAndJumpIfSmi(dst, object, &done); |
| 655 __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset)); | 648 __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset)); |
| 656 __ cmp(scratch1, heap_number_map); | 649 __ cmp(scratch1, heap_number_map); |
| 657 __ b(ne, not_number); | 650 __ b(ne, not_number); |
| 658 __ ConvertToInt32(object, | 651 __ ConvertToInt32(object, |
| 659 dst, | 652 dst, |
| 660 scratch1, | 653 scratch1, |
| 661 scratch2, | 654 scratch2, |
| 662 double_scratch, | 655 double_scratch, |
| 663 ¬_in_int32_range); | 656 ¬_in_int32_range); |
| 664 __ jmp(&done); | 657 __ jmp(&done); |
| 665 | 658 |
| 666 __ bind(¬_in_int32_range); | 659 __ bind(¬_in_int32_range); |
| 667 __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset)); | 660 __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
| 668 __ ldr(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset)); | 661 __ ldr(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
| 669 | 662 |
| 670 __ EmitOutOfInt32RangeTruncate(dst, | 663 __ EmitOutOfInt32RangeTruncate(dst, |
| 671 scratch1, | 664 scratch1, |
| 672 scratch2, | 665 scratch2, |
| 673 scratch3); | 666 scratch3); |
| 674 __ jmp(&done); | |
| 675 | |
| 676 __ bind(&is_smi); | |
| 677 __ SmiUntag(dst, object); | |
| 678 __ bind(&done); | 667 __ bind(&done); |
| 679 } | 668 } |
| 680 | 669 |
| 681 | 670 |
| 682 void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm, | 671 void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm, |
| 683 Register int_scratch, | 672 Register int_scratch, |
| 684 Destination destination, | 673 Destination destination, |
| 685 DwVfpRegister double_dst, | 674 DwVfpRegister double_dst, |
| 686 Register dst1, | 675 Register dst1, |
| 687 Register dst2, | 676 Register dst2, |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 840 DwVfpRegister double_scratch, | 829 DwVfpRegister double_scratch, |
| 841 Label* not_int32) { | 830 Label* not_int32) { |
| 842 ASSERT(!dst.is(object)); | 831 ASSERT(!dst.is(object)); |
| 843 ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object)); | 832 ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object)); |
| 844 ASSERT(!scratch1.is(scratch2) && | 833 ASSERT(!scratch1.is(scratch2) && |
| 845 !scratch1.is(scratch3) && | 834 !scratch1.is(scratch3) && |
| 846 !scratch2.is(scratch3)); | 835 !scratch2.is(scratch3)); |
| 847 | 836 |
| 848 Label done; | 837 Label done; |
| 849 | 838 |
| 850 // Untag the object into the destination register. | 839 __ UntagAndJumpIfSmi(dst, object, &done); |
| 851 __ SmiUntag(dst, object); | |
| 852 // Just return if the object is a smi. | |
| 853 __ JumpIfSmi(object, &done); | |
| 854 | 840 |
| 855 if (FLAG_debug_code) { | 841 if (FLAG_debug_code) { |
| 856 __ AbortIfNotRootValue(heap_number_map, | 842 __ AbortIfNotRootValue(heap_number_map, |
| 857 Heap::kHeapNumberMapRootIndex, | 843 Heap::kHeapNumberMapRootIndex, |
| 858 "HeapNumberMap register clobbered."); | 844 "HeapNumberMap register clobbered."); |
| 859 } | 845 } |
| 860 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); | 846 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); |
| 861 | 847 |
| 862 // Object is a heap number. | 848 // Object is a heap number. |
| 863 // Convert the floating point value to a 32-bit integer. | 849 // Convert the floating point value to a 32-bit integer. |
| (...skipping 2439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3303 CHECK_EQ(2 * kIntSize, elem_out - elem_start); | 3289 CHECK_EQ(2 * kIntSize, elem_out - elem_start); |
| 3304 } | 3290 } |
| 3305 #endif | 3291 #endif |
| 3306 | 3292 |
| 3307 // Find the address of the r1'st entry in the cache, i.e., &r0[r1*12]. | 3293 // Find the address of the r1'st entry in the cache, i.e., &r0[r1*12]. |
| 3308 __ add(r1, r1, Operand(r1, LSL, 1)); | 3294 __ add(r1, r1, Operand(r1, LSL, 1)); |
| 3309 __ add(cache_entry, cache_entry, Operand(r1, LSL, 2)); | 3295 __ add(cache_entry, cache_entry, Operand(r1, LSL, 2)); |
| 3310 // Check if cache matches: Double value is stored in uint32_t[2] array. | 3296 // Check if cache matches: Double value is stored in uint32_t[2] array. |
| 3311 __ ldm(ia, cache_entry, r4.bit() | r5.bit() | r6.bit()); | 3297 __ ldm(ia, cache_entry, r4.bit() | r5.bit() | r6.bit()); |
| 3312 __ cmp(r2, r4); | 3298 __ cmp(r2, r4); |
| 3313 __ b(ne, &calculate); | 3299 __ cmp(r3, r5, eq); |
| 3314 __ cmp(r3, r5); | |
| 3315 __ b(ne, &calculate); | 3300 __ b(ne, &calculate); |
| 3316 // Cache hit. Load result, cleanup and return. | 3301 // Cache hit. Load result, cleanup and return. |
| 3317 Counters* counters = masm->isolate()->counters(); | 3302 Counters* counters = masm->isolate()->counters(); |
| 3318 __ IncrementCounter( | 3303 __ IncrementCounter( |
| 3319 counters->transcendental_cache_hit(), 1, scratch0, scratch1); | 3304 counters->transcendental_cache_hit(), 1, scratch0, scratch1); |
| 3320 if (tagged) { | 3305 if (tagged) { |
| 3321 // Pop input value from stack and load result into r0. | 3306 // Pop input value from stack and load result into r0. |
| 3322 __ pop(); | 3307 __ pop(); |
| 3323 __ mov(r0, Operand(r6)); | 3308 __ mov(r0, Operand(r6)); |
| 3324 } else { | 3309 } else { |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3461 const Register heapnumbermap = r5; | 3446 const Register heapnumbermap = r5; |
| 3462 const Register heapnumber = r0; | 3447 const Register heapnumber = r0; |
| 3463 const DoubleRegister double_base = d1; | 3448 const DoubleRegister double_base = d1; |
| 3464 const DoubleRegister double_exponent = d2; | 3449 const DoubleRegister double_exponent = d2; |
| 3465 const DoubleRegister double_result = d3; | 3450 const DoubleRegister double_result = d3; |
| 3466 const DoubleRegister double_scratch = d0; | 3451 const DoubleRegister double_scratch = d0; |
| 3467 const SwVfpRegister single_scratch = s0; | 3452 const SwVfpRegister single_scratch = s0; |
| 3468 const Register scratch = r9; | 3453 const Register scratch = r9; |
| 3469 const Register scratch2 = r7; | 3454 const Register scratch2 = r7; |
| 3470 | 3455 |
| 3471 Label call_runtime, done, exponent_not_smi, int_exponent; | 3456 Label call_runtime, done, int_exponent; |
| 3472 if (exponent_type_ == ON_STACK) { | 3457 if (exponent_type_ == ON_STACK) { |
| 3473 Label base_is_smi, unpack_exponent; | 3458 Label base_is_smi, unpack_exponent; |
| 3474 // The exponent and base are supplied as arguments on the stack. | 3459 // The exponent and base are supplied as arguments on the stack. |
| 3475 // This can only happen if the stub is called from non-optimized code. | 3460 // This can only happen if the stub is called from non-optimized code. |
| 3476 // Load input parameters from stack to double registers. | 3461 // Load input parameters from stack to double registers. |
| 3477 __ ldr(base, MemOperand(sp, 1 * kPointerSize)); | 3462 __ ldr(base, MemOperand(sp, 1 * kPointerSize)); |
| 3478 __ ldr(exponent, MemOperand(sp, 0 * kPointerSize)); | 3463 __ ldr(exponent, MemOperand(sp, 0 * kPointerSize)); |
| 3479 | 3464 |
| 3480 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); | 3465 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); |
| 3481 | 3466 |
| 3482 __ JumpIfSmi(base, &base_is_smi); | 3467 __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); |
| 3483 __ ldr(scratch, FieldMemOperand(base, JSObject::kMapOffset)); | 3468 __ ldr(scratch, FieldMemOperand(base, JSObject::kMapOffset)); |
| 3484 __ cmp(scratch, heapnumbermap); | 3469 __ cmp(scratch, heapnumbermap); |
| 3485 __ b(ne, &call_runtime); | 3470 __ b(ne, &call_runtime); |
| 3486 | 3471 |
| 3487 __ vldr(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); | 3472 __ vldr(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); |
| 3488 __ jmp(&unpack_exponent); | 3473 __ jmp(&unpack_exponent); |
| 3489 | 3474 |
| 3490 __ bind(&base_is_smi); | 3475 __ bind(&base_is_smi); |
| 3491 __ SmiUntag(base); | 3476 __ vmov(single_scratch, scratch); |
| 3492 __ vmov(single_scratch, base); | |
| 3493 __ vcvt_f64_s32(double_base, single_scratch); | 3477 __ vcvt_f64_s32(double_base, single_scratch); |
| 3494 __ bind(&unpack_exponent); | 3478 __ bind(&unpack_exponent); |
| 3495 | 3479 |
| 3496 __ JumpIfNotSmi(exponent, &exponent_not_smi); | 3480 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); |
| 3497 __ SmiUntag(exponent); | |
| 3498 __ jmp(&int_exponent); | |
| 3499 | 3481 |
| 3500 __ bind(&exponent_not_smi); | |
| 3501 __ ldr(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); | 3482 __ ldr(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); |
| 3502 __ cmp(scratch, heapnumbermap); | 3483 __ cmp(scratch, heapnumbermap); |
| 3503 __ b(ne, &call_runtime); | 3484 __ b(ne, &call_runtime); |
| 3504 __ vldr(double_exponent, | 3485 __ vldr(double_exponent, |
| 3505 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 3486 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
| 3506 } else if (exponent_type_ == TAGGED) { | 3487 } else if (exponent_type_ == TAGGED) { |
| 3507 // Base is already in double_base. | 3488 // Base is already in double_base. |
| 3508 __ JumpIfNotSmi(exponent, &exponent_not_smi); | 3489 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); |
| 3509 __ SmiUntag(exponent); | |
| 3510 __ jmp(&int_exponent); | |
| 3511 | 3490 |
| 3512 __ bind(&exponent_not_smi); | |
| 3513 __ vldr(double_exponent, | 3491 __ vldr(double_exponent, |
| 3514 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 3492 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
| 3515 } | 3493 } |
| 3516 | 3494 |
| 3517 if (exponent_type_ != INTEGER) { | 3495 if (exponent_type_ != INTEGER) { |
| 3518 Label int_exponent_convert; | 3496 Label int_exponent_convert; |
| 3519 // Detect integer exponents stored as double. | 3497 // Detect integer exponents stored as double. |
| 3520 __ vcvt_u32_f64(single_scratch, double_exponent); | 3498 __ vcvt_u32_f64(single_scratch, double_exponent); |
| 3521 // We do not check for NaN or Infinity here because comparing numbers on | 3499 // We do not check for NaN or Infinity here because comparing numbers on |
| 3522 // ARM correctly distinguishes NaNs. We end up calling the built-in. | 3500 // ARM correctly distinguishes NaNs. We end up calling the built-in. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3575 __ CallCFunction( | 3553 __ CallCFunction( |
| 3576 ExternalReference::power_double_double_function(masm->isolate()), | 3554 ExternalReference::power_double_double_function(masm->isolate()), |
| 3577 0, 2); | 3555 0, 2); |
| 3578 } | 3556 } |
| 3579 __ pop(lr); | 3557 __ pop(lr); |
| 3580 __ GetCFunctionDoubleResult(double_result); | 3558 __ GetCFunctionDoubleResult(double_result); |
| 3581 __ jmp(&done); | 3559 __ jmp(&done); |
| 3582 | 3560 |
| 3583 __ bind(&int_exponent_convert); | 3561 __ bind(&int_exponent_convert); |
| 3584 __ vcvt_u32_f64(single_scratch, double_exponent); | 3562 __ vcvt_u32_f64(single_scratch, double_exponent); |
| 3585 __ vmov(exponent, single_scratch); | 3563 __ vmov(scratch, single_scratch); |
| 3586 } | 3564 } |
| 3587 | 3565 |
| 3588 // Calculate power with integer exponent. | 3566 // Calculate power with integer exponent. |
| 3589 __ bind(&int_exponent); | 3567 __ bind(&int_exponent); |
| 3590 | 3568 // Exponent has been stored into scratch as untagged integer. |
| 3591 __ mov(scratch, exponent); // Back up exponent. | 3569 __ mov(exponent, scratch); // Back up exponent. |
| 3592 __ vmov(double_scratch, double_base); // Back up base. | 3570 __ vmov(double_scratch, double_base); // Back up base. |
| 3593 __ vmov(double_result, 1.0); | 3571 __ vmov(double_result, 1.0); |
| 3594 | 3572 |
| 3595 // Get absolute value of exponent. | 3573 // Get absolute value of exponent. |
| 3596 __ cmp(scratch, Operand(0)); | 3574 __ cmp(scratch, Operand(0)); |
| 3597 __ mov(scratch2, Operand(0), LeaveCC, mi); | 3575 __ mov(scratch2, Operand(0), LeaveCC, mi); |
| 3598 __ sub(scratch, scratch2, scratch, LeaveCC, mi); | 3576 __ sub(scratch, scratch2, scratch, LeaveCC, mi); |
| 3599 | 3577 |
| 3600 Label while_true; | 3578 Label while_true; |
| 3601 __ bind(&while_true); | 3579 __ bind(&while_true); |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4091 } | 4069 } |
| 4092 | 4070 |
| 4093 // Check that the left hand is a JS object and load map. | 4071 // Check that the left hand is a JS object and load map. |
| 4094 __ JumpIfSmi(object, ¬_js_object); | 4072 __ JumpIfSmi(object, ¬_js_object); |
| 4095 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); | 4073 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); |
| 4096 | 4074 |
| 4097 // If there is a call site cache don't look in the global cache, but do the | 4075 // If there is a call site cache don't look in the global cache, but do the |
| 4098 // real lookup and update the call site cache. | 4076 // real lookup and update the call site cache. |
| 4099 if (!HasCallSiteInlineCheck()) { | 4077 if (!HasCallSiteInlineCheck()) { |
| 4100 Label miss; | 4078 Label miss; |
| 4101 __ LoadRoot(ip, Heap::kInstanceofCacheFunctionRootIndex); | 4079 __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex); |
| 4102 __ cmp(function, ip); | |
| 4103 __ b(ne, &miss); | 4080 __ b(ne, &miss); |
| 4104 __ LoadRoot(ip, Heap::kInstanceofCacheMapRootIndex); | 4081 __ CompareRoot(map, Heap::kInstanceofCacheMapRootIndex); |
| 4105 __ cmp(map, ip); | |
| 4106 __ b(ne, &miss); | 4082 __ b(ne, &miss); |
| 4107 __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); | 4083 __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); |
| 4108 __ Ret(HasArgsInRegisters() ? 0 : 2); | 4084 __ Ret(HasArgsInRegisters() ? 0 : 2); |
| 4109 | 4085 |
| 4110 __ bind(&miss); | 4086 __ bind(&miss); |
| 4111 } | 4087 } |
| 4112 | 4088 |
| 4113 // Get the prototype of the function. | 4089 // Get the prototype of the function. |
| 4114 __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true); | 4090 __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true); |
| 4115 | 4091 |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4720 // regexp_data: RegExp data (FixedArray) | 4696 // regexp_data: RegExp data (FixedArray) |
| 4721 // Check that the fourth object is a JSArray object. | 4697 // Check that the fourth object is a JSArray object. |
| 4722 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); | 4698 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); |
| 4723 __ JumpIfSmi(r0, &runtime); | 4699 __ JumpIfSmi(r0, &runtime); |
| 4724 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); | 4700 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); |
| 4725 __ b(ne, &runtime); | 4701 __ b(ne, &runtime); |
| 4726 // Check that the JSArray is in fast case. | 4702 // Check that the JSArray is in fast case. |
| 4727 __ ldr(last_match_info_elements, | 4703 __ ldr(last_match_info_elements, |
| 4728 FieldMemOperand(r0, JSArray::kElementsOffset)); | 4704 FieldMemOperand(r0, JSArray::kElementsOffset)); |
| 4729 __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); | 4705 __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); |
| 4730 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 4706 __ CompareRoot(r0, Heap::kFixedArrayMapRootIndex); |
| 4731 __ cmp(r0, ip); | |
| 4732 __ b(ne, &runtime); | 4707 __ b(ne, &runtime); |
| 4733 // Check that the last match info has space for the capture registers and the | 4708 // Check that the last match info has space for the capture registers and the |
| 4734 // additional information. | 4709 // additional information. |
| 4735 __ ldr(r0, | 4710 __ ldr(r0, |
| 4736 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); | 4711 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); |
| 4737 __ add(r2, r2, Operand(RegExpImpl::kLastMatchOverhead)); | 4712 __ add(r2, r2, Operand(RegExpImpl::kLastMatchOverhead)); |
| 4738 __ cmp(r2, Operand(r0, ASR, kSmiTagSize)); | 4713 __ cmp(r2, Operand(r0, ASR, kSmiTagSize)); |
| 4739 __ b(gt, &runtime); | 4714 __ b(gt, &runtime); |
| 4740 | 4715 |
| 4741 // Reset offset for possibly sliced string. | 4716 // Reset offset for possibly sliced string. |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5075 __ add(r3, r0, Operand(JSRegExpResult::kSize)); | 5050 __ add(r3, r0, Operand(JSRegExpResult::kSize)); |
| 5076 __ mov(r4, Operand(factory->empty_fixed_array())); | 5051 __ mov(r4, Operand(factory->empty_fixed_array())); |
| 5077 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset)); | 5052 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset)); |
| 5078 __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); | 5053 __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); |
| 5079 __ ldr(r2, ContextOperand(r2, Context::REGEXP_RESULT_MAP_INDEX)); | 5054 __ ldr(r2, ContextOperand(r2, Context::REGEXP_RESULT_MAP_INDEX)); |
| 5080 __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); | 5055 __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); |
| 5081 __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5056 __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 5082 | 5057 |
| 5083 // Set input, index and length fields from arguments. | 5058 // Set input, index and length fields from arguments. |
| 5084 __ ldr(r1, MemOperand(sp, kPointerSize * 0)); | 5059 __ ldr(r1, MemOperand(sp, kPointerSize * 0)); |
| 5060 __ ldr(r2, MemOperand(sp, kPointerSize * 1)); |
| 5061 __ ldr(r6, MemOperand(sp, kPointerSize * 2)); |
| 5085 __ str(r1, FieldMemOperand(r0, JSRegExpResult::kInputOffset)); | 5062 __ str(r1, FieldMemOperand(r0, JSRegExpResult::kInputOffset)); |
| 5086 __ ldr(r1, MemOperand(sp, kPointerSize * 1)); | 5063 __ str(r2, FieldMemOperand(r0, JSRegExpResult::kIndexOffset)); |
| 5087 __ str(r1, FieldMemOperand(r0, JSRegExpResult::kIndexOffset)); | 5064 __ str(r6, FieldMemOperand(r0, JSArray::kLengthOffset)); |
| 5088 __ ldr(r1, MemOperand(sp, kPointerSize * 2)); | |
| 5089 __ str(r1, FieldMemOperand(r0, JSArray::kLengthOffset)); | |
| 5090 | 5065 |
| 5091 // Fill out the elements FixedArray. | 5066 // Fill out the elements FixedArray. |
| 5092 // r0: JSArray, tagged. | 5067 // r0: JSArray, tagged. |
| 5093 // r3: FixedArray, tagged. | 5068 // r3: FixedArray, tagged. |
| 5094 // r5: Number of elements in array, untagged. | 5069 // r5: Number of elements in array, untagged. |
| 5095 | 5070 |
| 5096 // Set map. | 5071 // Set map. |
| 5097 __ mov(r2, Operand(factory->fixed_array_map())); | 5072 __ mov(r2, Operand(factory->fixed_array_map())); |
| 5098 __ str(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); | 5073 __ str(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); |
| 5099 // Set FixedArray length. | 5074 // Set FixedArray length. |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5429 __ tst(code_, | 5404 __ tst(code_, |
| 5430 Operand(kSmiTagMask | | 5405 Operand(kSmiTagMask | |
| 5431 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); | 5406 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); |
| 5432 __ b(ne, &slow_case_); | 5407 __ b(ne, &slow_case_); |
| 5433 | 5408 |
| 5434 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); | 5409 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); |
| 5435 // At this point code register contains smi tagged ASCII char code. | 5410 // At this point code register contains smi tagged ASCII char code. |
| 5436 STATIC_ASSERT(kSmiTag == 0); | 5411 STATIC_ASSERT(kSmiTag == 0); |
| 5437 __ add(result_, result_, Operand(code_, LSL, kPointerSizeLog2 - kSmiTagSize)); | 5412 __ add(result_, result_, Operand(code_, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 5438 __ ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); | 5413 __ ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); |
| 5439 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 5414 __ CompareRoot(result_, Heap::kUndefinedValueRootIndex); |
| 5440 __ cmp(result_, Operand(ip)); | |
| 5441 __ b(eq, &slow_case_); | 5415 __ b(eq, &slow_case_); |
| 5442 __ bind(&exit_); | 5416 __ bind(&exit_); |
| 5443 } | 5417 } |
| 5444 | 5418 |
| 5445 | 5419 |
| 5446 void StringCharFromCodeGenerator::GenerateSlow( | 5420 void StringCharFromCodeGenerator::GenerateSlow( |
| 5447 MacroAssembler* masm, | 5421 MacroAssembler* masm, |
| 5448 const RuntimeCallHelper& call_helper) { | 5422 const RuntimeCallHelper& call_helper) { |
| 5449 __ Abort("Unexpected fallthrough to CharFromCode slow case"); | 5423 __ Abort("Unexpected fallthrough to CharFromCode slow case"); |
| 5450 | 5424 |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5858 __ Ldrd(r2, r3, MemOperand(sp, kToOffset)); | 5832 __ Ldrd(r2, r3, MemOperand(sp, kToOffset)); |
| 5859 STATIC_ASSERT(kFromOffset == kToOffset + 4); | 5833 STATIC_ASSERT(kFromOffset == kToOffset + 4); |
| 5860 STATIC_ASSERT(kSmiTag == 0); | 5834 STATIC_ASSERT(kSmiTag == 0); |
| 5861 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 5835 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
| 5862 | 5836 |
| 5863 // I.e., arithmetic shift right by one un-smi-tags. | 5837 // I.e., arithmetic shift right by one un-smi-tags. |
| 5864 __ mov(r2, Operand(r2, ASR, 1), SetCC); | 5838 __ mov(r2, Operand(r2, ASR, 1), SetCC); |
| 5865 __ mov(r3, Operand(r3, ASR, 1), SetCC, cc); | 5839 __ mov(r3, Operand(r3, ASR, 1), SetCC, cc); |
| 5866 // If either to or from had the smi tag bit set, then carry is set now. | 5840 // If either to or from had the smi tag bit set, then carry is set now. |
| 5867 __ b(cs, &runtime); // Either "from" or "to" is not a smi. | 5841 __ b(cs, &runtime); // Either "from" or "to" is not a smi. |
| 5868 __ b(mi, &runtime); // From is negative. | 5842 // We want to bailout to runtime here if From is negative. In that case, the |
| 5869 | 5843 // next instruction is not executed and we fall through to bailing out to |
| 5844 // runtime. pl is the opposite of mi. |
| 5870 // Both r2 and r3 are untagged integers. | 5845 // Both r2 and r3 are untagged integers. |
| 5871 __ sub(r2, r2, Operand(r3), SetCC); | 5846 __ sub(r2, r2, Operand(r3), SetCC, pl); |
| 5872 __ b(mi, &runtime); // Fail if from > to. | 5847 __ b(mi, &runtime); // Fail if from > to. |
| 5873 | 5848 |
| 5874 // Make sure first argument is a string. | 5849 // Make sure first argument is a string. |
| 5875 __ ldr(r0, MemOperand(sp, kStringOffset)); | 5850 __ ldr(r0, MemOperand(sp, kStringOffset)); |
| 5876 STATIC_ASSERT(kSmiTag == 0); | 5851 STATIC_ASSERT(kSmiTag == 0); |
| 5877 __ JumpIfSmi(r0, &runtime); | 5852 __ JumpIfSmi(r0, &runtime); |
| 5878 Condition is_string = masm->IsObjectStringType(r0, r1); | 5853 Condition is_string = masm->IsObjectStringType(r0, r1); |
| 5879 __ b(NegateCondition(is_string), &runtime); | 5854 __ b(NegateCondition(is_string), &runtime); |
| 5880 | 5855 |
| 5881 // Short-cut for the case of trivial substring. | 5856 // Short-cut for the case of trivial substring. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5934 __ CompareRoot(r5, Heap::kEmptyStringRootIndex); | 5909 __ CompareRoot(r5, Heap::kEmptyStringRootIndex); |
| 5935 __ b(ne, &runtime); | 5910 __ b(ne, &runtime); |
| 5936 __ ldr(r5, FieldMemOperand(r0, ConsString::kFirstOffset)); | 5911 __ ldr(r5, FieldMemOperand(r0, ConsString::kFirstOffset)); |
| 5937 // Update instance type. | 5912 // Update instance type. |
| 5938 __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset)); | 5913 __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset)); |
| 5939 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); | 5914 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
| 5940 __ jmp(&underlying_unpacked); | 5915 __ jmp(&underlying_unpacked); |
| 5941 | 5916 |
| 5942 __ bind(&sliced_string); | 5917 __ bind(&sliced_string); |
| 5943 // Sliced string. Fetch parent and correct start index by offset. | 5918 // Sliced string. Fetch parent and correct start index by offset. |
| 5944 __ ldr(r5, FieldMemOperand(r0, SlicedString::kOffsetOffset)); | 5919 __ ldr(r4, FieldMemOperand(r0, SlicedString::kOffsetOffset)); |
| 5945 __ add(r3, r3, Operand(r5, ASR, 1)); | |
| 5946 __ ldr(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); | 5920 __ ldr(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); |
| 5921 __ add(r3, r3, Operand(r4, ASR, 1)); // Add offset to index. |
| 5947 // Update instance type. | 5922 // Update instance type. |
| 5948 __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset)); | 5923 __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset)); |
| 5949 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); | 5924 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
| 5950 __ jmp(&underlying_unpacked); | 5925 __ jmp(&underlying_unpacked); |
| 5951 | 5926 |
| 5952 __ bind(&seq_or_external_string); | 5927 __ bind(&seq_or_external_string); |
| 5953 // Sequential or external string. Just move string to the expected register. | 5928 // Sequential or external string. Just move string to the expected register. |
| 5954 __ mov(r5, r0); | 5929 __ mov(r5, r0); |
| 5955 | 5930 |
| 5956 __ bind(&underlying_unpacked); | 5931 __ bind(&underlying_unpacked); |
| (...skipping 1423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7380 __ StoreNumberToDoubleElements(r0, r3, r1, r5, r6, r7, r9, r10, | 7355 __ StoreNumberToDoubleElements(r0, r3, r1, r5, r6, r7, r9, r10, |
| 7381 &slow_elements); | 7356 &slow_elements); |
| 7382 __ Ret(); | 7357 __ Ret(); |
| 7383 } | 7358 } |
| 7384 | 7359 |
| 7385 #undef __ | 7360 #undef __ |
| 7386 | 7361 |
| 7387 } } // namespace v8::internal | 7362 } } // namespace v8::internal |
| 7388 | 7363 |
| 7389 #endif // V8_TARGET_ARCH_ARM | 7364 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |