Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(741)

Side by Side Diff: src/arm/code-stubs-arm.cc

Issue 21063002: Out-of-line constant pool on Arm: Stage 1 - Free up r7 for use as constant pool pointer register (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix typo Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 Counters* counters = masm->isolate()->counters(); 326 Counters* counters = masm->isolate()->counters();
327 327
328 Label gc; 328 Label gc;
329 329
330 // Pop the function info from the stack. 330 // Pop the function info from the stack.
331 __ pop(r3); 331 __ pop(r3);
332 332
333 // Attempt to allocate new JSFunction in new space. 333 // Attempt to allocate new JSFunction in new space.
334 __ Allocate(JSFunction::kSize, r0, r1, r2, &gc, TAG_OBJECT); 334 __ Allocate(JSFunction::kSize, r0, r1, r2, &gc, TAG_OBJECT);
335 335
336 __ IncrementCounter(counters->fast_new_closure_total(), 1, r6, r7); 336 __ IncrementCounter(counters->fast_new_closure_total(), 1, r6, r4);
337 337
338 int map_index = Context::FunctionMapIndex(language_mode_, is_generator_); 338 int map_index = Context::FunctionMapIndex(language_mode_, is_generator_);
339 339
340 // Compute the function map in the current native context and set that 340 // Compute the function map in the current native context and set that
341 // as the map of the allocated object. 341 // as the map of the allocated object.
342 __ ldr(r2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 342 __ ldr(r2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
343 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kNativeContextOffset)); 343 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kNativeContextOffset));
344 __ ldr(r5, MemOperand(r2, Context::SlotOffset(map_index))); 344 __ ldr(r5, MemOperand(r2, Context::SlotOffset(map_index)));
345 __ str(r5, FieldMemOperand(r0, HeapObject::kMapOffset)); 345 __ str(r5, FieldMemOperand(r0, HeapObject::kMapOffset));
346 346
(...skipping 24 matching lines...) Expand all
371 __ str(r4, FieldMemOperand(r0, JSFunction::kNextFunctionLinkOffset)); 371 __ str(r4, FieldMemOperand(r0, JSFunction::kNextFunctionLinkOffset));
372 __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset)); 372 __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
373 __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); 373 __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
374 __ str(r3, FieldMemOperand(r0, JSFunction::kCodeEntryOffset)); 374 __ str(r3, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
375 375
376 // Return result. The argument function info has been popped already. 376 // Return result. The argument function info has been popped already.
377 __ Ret(); 377 __ Ret();
378 378
379 __ bind(&check_optimized); 379 __ bind(&check_optimized);
380 380
381 __ IncrementCounter(counters->fast_new_closure_try_optimized(), 1, r6, r7); 381 __ IncrementCounter(counters->fast_new_closure_try_optimized(), 1, r6, r4);
382 382
383 // r2 holds native context, r1 points to fixed array of 3-element entries 383 // r2 holds native context, r1 points to fixed array of 3-element entries
384 // (native context, optimized code, literals). 384 // (native context, optimized code, literals).
385 // The optimized code map must never be empty, so check the first elements. 385 // The optimized code map must never be empty, so check the first elements.
386 Label install_optimized; 386 Label install_optimized;
387 // Speculatively move code object into r4. 387 // Speculatively move code object into r4.
388 __ ldr(r4, FieldMemOperand(r1, SharedFunctionInfo::kFirstCodeSlot)); 388 __ ldr(r4, FieldMemOperand(r1, SharedFunctionInfo::kFirstCodeSlot));
389 __ ldr(r5, FieldMemOperand(r1, SharedFunctionInfo::kFirstContextSlot)); 389 __ ldr(r5, FieldMemOperand(r1, SharedFunctionInfo::kFirstContextSlot));
390 __ cmp(r2, r5); 390 __ cmp(r2, r5);
391 __ b(eq, &install_optimized); 391 __ b(eq, &install_optimized);
(...skipping 12 matching lines...) Expand all
404 __ cmp(r2, r5); 404 __ cmp(r2, r5);
405 __ b(ne, &loop); 405 __ b(ne, &loop);
406 // Hit: fetch the optimized code. 406 // Hit: fetch the optimized code.
407 __ add(r5, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 407 __ add(r5, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
408 __ add(r5, r5, Operand::PointerOffsetFromSmiKey(r4)); 408 __ add(r5, r5, Operand::PointerOffsetFromSmiKey(r4));
409 __ add(r5, r5, Operand(kPointerSize)); 409 __ add(r5, r5, Operand(kPointerSize));
410 __ ldr(r4, MemOperand(r5)); 410 __ ldr(r4, MemOperand(r5));
411 411
412 __ bind(&install_optimized); 412 __ bind(&install_optimized);
413 __ IncrementCounter(counters->fast_new_closure_install_optimized(), 413 __ IncrementCounter(counters->fast_new_closure_install_optimized(),
414 1, r6, r7); 414 1, r6, r5);
415 415
416 // TODO(fschneider): Idea: store proper code pointers in the map and either 416 // TODO(fschneider): Idea: store proper code pointers in the map and either
417 // unmangle them on marking or do nothing as the whole map is discarded on 417 // unmangle them on marking or do nothing as the whole map is discarded on
418 // major GC anyway. 418 // major GC anyway.
419 __ add(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); 419 __ add(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag));
420 __ str(r4, FieldMemOperand(r0, JSFunction::kCodeEntryOffset)); 420 __ str(r4, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
421 421
422 // Now link a function into a list of optimized functions. 422 // Now link a function into a list of optimized functions.
423 __ ldr(r4, ContextOperand(r2, Context::OPTIMIZED_FUNCTIONS_LIST)); 423 __ ldr(r4, ContextOperand(r2, Context::OPTIMIZED_FUNCTIONS_LIST));
424 424
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 } else { 842 } else {
843 // Smi compared non-strictly with a non-Smi non-heap-number. Call 843 // Smi compared non-strictly with a non-Smi non-heap-number. Call
844 // the runtime. 844 // the runtime.
845 __ b(ne, slow); 845 __ b(ne, slow);
846 } 846 }
847 847
848 // Lhs is a smi, rhs is a number. 848 // Lhs is a smi, rhs is a number.
849 // Convert lhs to a double in d7. 849 // Convert lhs to a double in d7.
850 __ SmiToDouble(d7, lhs); 850 __ SmiToDouble(d7, lhs);
851 // Load the double from rhs, tagged HeapNumber r0, to d6. 851 // Load the double from rhs, tagged HeapNumber r0, to d6.
852 __ sub(r7, rhs, Operand(kHeapObjectTag)); 852 __ sub(ip, rhs, Operand(kHeapObjectTag));
853 __ vldr(d6, r7, HeapNumber::kValueOffset); 853 __ vldr(d6, ip, HeapNumber::kValueOffset);
ulan 2013/07/30 09:45:19 You can fold it into vldr(d6, rhs, HeapNumber::kVa
danno 2013/07/30 10:34:29 Actually, you can't IIRC, the offset to vldr has t
rmcilroy 2013/07/30 11:39:44 Folded (which causes vldr "instruction" to generat
854 854
855 // We now have both loaded as doubles but we can skip the lhs nan check 855 // We now have both loaded as doubles but we can skip the lhs nan check
856 // since it's a smi. 856 // since it's a smi.
857 __ jmp(lhs_not_nan); 857 __ jmp(lhs_not_nan);
858 858
859 __ bind(&rhs_is_smi); 859 __ bind(&rhs_is_smi);
860 // Rhs is a smi. Check whether the non-smi lhs is a heap number. 860 // Rhs is a smi. Check whether the non-smi lhs is a heap number.
861 __ CompareObjectType(lhs, r4, r4, HEAP_NUMBER_TYPE); 861 __ CompareObjectType(lhs, r4, r4, HEAP_NUMBER_TYPE);
862 if (strict) { 862 if (strict) {
863 // If lhs is not a number and rhs is a smi then strict equality cannot 863 // If lhs is not a number and rhs is a smi then strict equality cannot
864 // succeed. Return non-equal. 864 // succeed. Return non-equal.
865 // If lhs is r0 then there is already a non zero value in it. 865 // If lhs is r0 then there is already a non zero value in it.
866 if (!lhs.is(r0)) { 866 if (!lhs.is(r0)) {
867 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); 867 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne);
868 } 868 }
869 __ Ret(ne); 869 __ Ret(ne);
870 } else { 870 } else {
871 // Smi compared non-strictly with a non-smi non-heap-number. Call 871 // Smi compared non-strictly with a non-smi non-heap-number. Call
872 // the runtime. 872 // the runtime.
873 __ b(ne, slow); 873 __ b(ne, slow);
874 } 874 }
875 875
876 // Rhs is a smi, lhs is a heap number. 876 // Rhs is a smi, lhs is a heap number.
877 // Load the double from lhs, tagged HeapNumber r1, to d7. 877 // Load the double from lhs, tagged HeapNumber r1, to d7.
878 __ sub(r7, lhs, Operand(kHeapObjectTag)); 878 __ sub(ip, lhs, Operand(kHeapObjectTag));
879 __ vldr(d7, r7, HeapNumber::kValueOffset); 879 __ vldr(d7, ip, HeapNumber::kValueOffset);
ulan 2013/07/30 09:45:19 Fold this as above.
rmcilroy 2013/07/30 11:39:44 Done.
880 // Convert rhs to a double in d6 . 880 // Convert rhs to a double in d6 .
881 __ SmiToDouble(d6, rhs); 881 __ SmiToDouble(d6, rhs);
882 // Fall through to both_loaded_as_doubles. 882 // Fall through to both_loaded_as_doubles.
883 } 883 }
884 884
885 885
886 // See comment at call site. 886 // See comment at call site.
887 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, 887 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
888 Register lhs, 888 Register lhs,
889 Register rhs) { 889 Register rhs) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 (lhs.is(r1) && rhs.is(r0))); 937 (lhs.is(r1) && rhs.is(r0)));
938 938
939 __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE); 939 __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE);
940 __ b(ne, not_heap_numbers); 940 __ b(ne, not_heap_numbers);
941 __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset)); 941 __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset));
942 __ cmp(r2, r3); 942 __ cmp(r2, r3);
943 __ b(ne, slow); // First was a heap number, second wasn't. Go slow case. 943 __ b(ne, slow); // First was a heap number, second wasn't. Go slow case.
944 944
945 // Both are heap numbers. Load them up then jump to the code we have 945 // Both are heap numbers. Load them up then jump to the code we have
946 // for that. 946 // for that.
947 __ sub(r7, rhs, Operand(kHeapObjectTag)); 947 __ sub(r3, rhs, Operand(kHeapObjectTag));
948 __ vldr(d6, r7, HeapNumber::kValueOffset); 948 __ vldr(d6, r3, HeapNumber::kValueOffset);
949 __ sub(r7, lhs, Operand(kHeapObjectTag)); 949 __ sub(r3, lhs, Operand(kHeapObjectTag));
950 __ vldr(d7, r7, HeapNumber::kValueOffset); 950 __ vldr(d7, r3, HeapNumber::kValueOffset);
ulan 2013/07/30 09:45:19 Fold these too as above.
rmcilroy 2013/07/30 11:39:44 Done.
951 __ jmp(both_loaded_as_doubles); 951 __ jmp(both_loaded_as_doubles);
952 } 952 }
953 953
954 954
955 // Fast negative check for internalized-to-internalized equality. 955 // Fast negative check for internalized-to-internalized equality.
956 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, 956 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
957 Register lhs, 957 Register lhs,
958 Register rhs, 958 Register rhs,
959 Label* possible_strings, 959 Label* possible_strings,
960 Label* not_both_strings) { 960 Label* not_both_strings) {
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
1370 } 1370 }
1371 1371
1372 1372
1373 void BinaryOpStub::GenerateTypeTransitionWithSavedArgs( 1373 void BinaryOpStub::GenerateTypeTransitionWithSavedArgs(
1374 MacroAssembler* masm) { 1374 MacroAssembler* masm) {
1375 UNIMPLEMENTED(); 1375 UNIMPLEMENTED();
1376 } 1376 }
1377 1377
1378 1378
1379 void BinaryOpStub_GenerateSmiSmiOperation(MacroAssembler* masm, 1379 void BinaryOpStub_GenerateSmiSmiOperation(MacroAssembler* masm,
1380 Token::Value op) { 1380 Token::Value op,
1381 Register scratch1,
1382 Register scratch2) {
1381 Register left = r1; 1383 Register left = r1;
1382 Register right = r0; 1384 Register right = r0;
1383 Register scratch1 = r7;
1384 Register scratch2 = r9;
1385 1385
1386 ASSERT(right.is(r0)); 1386 ASSERT(right.is(r0));
1387 STATIC_ASSERT(kSmiTag == 0); 1387 STATIC_ASSERT(kSmiTag == 0);
1388 1388
1389 Label not_smi_result; 1389 Label not_smi_result;
1390 switch (op) { 1390 switch (op) {
1391 case Token::ADD: 1391 case Token::ADD:
1392 __ add(right, left, Operand(right), SetCC); // Add optimistically. 1392 __ add(right, left, Operand(right), SetCC); // Add optimistically.
1393 __ Ret(vc); 1393 __ Ret(vc);
1394 __ sub(right, right, Operand(left)); // Revert optimistic add. 1394 __ sub(right, right, Operand(left)); // Revert optimistic add.
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1591 1591
1592 1592
1593 void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm, 1593 void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
1594 BinaryOpIC::TypeInfo left_type, 1594 BinaryOpIC::TypeInfo left_type,
1595 BinaryOpIC::TypeInfo right_type, 1595 BinaryOpIC::TypeInfo right_type,
1596 bool smi_operands, 1596 bool smi_operands,
1597 Label* not_numbers, 1597 Label* not_numbers,
1598 Label* gc_required, 1598 Label* gc_required,
1599 Label* miss, 1599 Label* miss,
1600 Token::Value op, 1600 Token::Value op,
1601 OverwriteMode mode) { 1601 OverwriteMode mode,
1602 Register scratch1,
1603 Register scratch2,
1604 Register scratch3,
1605 Register scratch4) {
1602 Register left = r1; 1606 Register left = r1;
1603 Register right = r0; 1607 Register right = r0;
1604 Register scratch1 = r6; 1608 Register result = scratch3;
1605 Register scratch2 = r7;
1606 Register scratch3 = r4;
1607 1609
1608 ASSERT(smi_operands || (not_numbers != NULL)); 1610 ASSERT(smi_operands || (not_numbers != NULL));
1609 if (smi_operands) { 1611 if (smi_operands) {
1610 __ AssertSmi(left); 1612 __ AssertSmi(left);
1611 __ AssertSmi(right); 1613 __ AssertSmi(right);
1612 } 1614 }
1613 if (left_type == BinaryOpIC::SMI) { 1615 if (left_type == BinaryOpIC::SMI) {
1614 __ JumpIfNotSmi(left, miss); 1616 __ JumpIfNotSmi(left, miss);
1615 } 1617 }
1616 if (right_type == BinaryOpIC::SMI) { 1618 if (right_type == BinaryOpIC::SMI) {
1617 __ JumpIfNotSmi(right, miss); 1619 __ JumpIfNotSmi(right, miss);
1618 } 1620 }
1619 1621
1620 Register heap_number_map = r9; 1622 Register heap_number_map = scratch4;
1621 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 1623 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
1622 1624
1623 switch (op) { 1625 switch (op) {
1624 case Token::ADD: 1626 case Token::ADD:
1625 case Token::SUB: 1627 case Token::SUB:
1626 case Token::MUL: 1628 case Token::MUL:
1627 case Token::DIV: 1629 case Token::DIV:
1628 case Token::MOD: { 1630 case Token::MOD: {
1629 // Allocate new heap number for result. 1631 // Allocate new heap number for result.
1630 Register result = r5;
1631 BinaryOpStub_GenerateHeapResultAllocation( 1632 BinaryOpStub_GenerateHeapResultAllocation(
1632 masm, result, heap_number_map, scratch1, scratch2, gc_required, mode); 1633 masm, result, heap_number_map, scratch1, scratch2, gc_required, mode);
1633 1634
1634 // Load left and right operands into d0 and d1. 1635 // Load left and right operands into d0 and d1.
1635 if (smi_operands) { 1636 if (smi_operands) {
1636 __ SmiToDouble(d1, right); 1637 __ SmiToDouble(d1, right);
1637 __ SmiToDouble(d0, left); 1638 __ SmiToDouble(d0, left);
1638 } else { 1639 } else {
1639 // Load right operand into d1. 1640 // Load right operand into d1.
1640 if (right_type == BinaryOpIC::INT32) { 1641 if (right_type == BinaryOpIC::INT32) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1743 default: 1744 default:
1744 UNREACHABLE(); 1745 UNREACHABLE();
1745 } 1746 }
1746 1747
1747 // Check that the *signed* result fits in a smi. 1748 // Check that the *signed* result fits in a smi.
1748 __ TrySmiTag(r0, r2, &result_not_a_smi); 1749 __ TrySmiTag(r0, r2, &result_not_a_smi);
1749 __ Ret(); 1750 __ Ret();
1750 1751
1751 // Allocate new heap number for result. 1752 // Allocate new heap number for result.
1752 __ bind(&result_not_a_smi); 1753 __ bind(&result_not_a_smi);
1753 Register result = r5;
1754 if (smi_operands) { 1754 if (smi_operands) {
1755 __ AllocateHeapNumber( 1755 __ AllocateHeapNumber(
1756 result, scratch1, scratch2, heap_number_map, gc_required); 1756 result, scratch1, scratch2, heap_number_map, gc_required);
1757 } else { 1757 } else {
1758 BinaryOpStub_GenerateHeapResultAllocation( 1758 BinaryOpStub_GenerateHeapResultAllocation(
1759 masm, result, heap_number_map, scratch1, scratch2, gc_required, 1759 masm, result, heap_number_map, scratch1, scratch2, gc_required,
1760 mode); 1760 mode);
1761 } 1761 }
1762 1762
1763 // r2: Answer as signed int32. 1763 // r2: Answer as signed int32.
1764 // r5: Heap number to write answer into. 1764 // r5: Heap number to write answer into.
JF 2013/07/29 17:20:09 Update comment.
rmcilroy 2013/07/30 11:39:44 Done.
1765 1765
1766 // Nothing can go wrong now, so move the heap number to r0, which is the 1766 // Nothing can go wrong now, so move the heap number to r0, which is the
1767 // result. 1767 // result.
1768 __ mov(r0, Operand(r5)); 1768 __ mov(r0, Operand(result));
1769 1769
1770 // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As 1770 // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As
1771 // mentioned above SHR needs to always produce a positive result. 1771 // mentioned above SHR needs to always produce a positive result.
1772 __ vmov(s0, r2); 1772 __ vmov(s0, r2);
1773 if (op == Token::SHR) { 1773 if (op == Token::SHR) {
1774 __ vcvt_f64_u32(d0, s0); 1774 __ vcvt_f64_u32(d0, s0);
1775 } else { 1775 } else {
1776 __ vcvt_f64_s32(d0, s0); 1776 __ vcvt_f64_s32(d0, s0);
1777 } 1777 }
1778 __ sub(r3, r0, Operand(kHeapObjectTag)); 1778 __ sub(r3, r0, Operand(kHeapObjectTag));
(...skipping 10 matching lines...) Expand all
1789 // Generate the smi code. If the operation on smis are successful this return is 1789 // Generate the smi code. If the operation on smis are successful this return is
1790 // generated. If the result is not a smi and heap number allocation is not 1790 // generated. If the result is not a smi and heap number allocation is not
1791 // requested the code falls through. If number allocation is requested but a 1791 // requested the code falls through. If number allocation is requested but a
1792 // heap number cannot be allocated the code jumps to the label gc_required. 1792 // heap number cannot be allocated the code jumps to the label gc_required.
1793 void BinaryOpStub_GenerateSmiCode( 1793 void BinaryOpStub_GenerateSmiCode(
1794 MacroAssembler* masm, 1794 MacroAssembler* masm,
1795 Label* use_runtime, 1795 Label* use_runtime,
1796 Label* gc_required, 1796 Label* gc_required,
1797 Token::Value op, 1797 Token::Value op,
1798 BinaryOpStub::SmiCodeGenerateHeapNumberResults allow_heapnumber_results, 1798 BinaryOpStub::SmiCodeGenerateHeapNumberResults allow_heapnumber_results,
1799 OverwriteMode mode) { 1799 OverwriteMode mode,
1800 Register scratch1,
1801 Register scratch2) {
1800 Label not_smis; 1802 Label not_smis;
1801 1803
1802 Register left = r1; 1804 Register left = r1;
1803 Register right = r0; 1805 Register right = r0;
1804 Register scratch1 = r7;
1805 1806
1806 // Perform combined smi check on both operands. 1807 // Perform combined smi check on both operands.
1807 __ orr(scratch1, left, Operand(right)); 1808 __ orr(scratch1, left, Operand(right));
1808 __ JumpIfNotSmi(scratch1, &not_smis); 1809 __ JumpIfNotSmi(scratch1, &not_smis);
1809 1810
1810 // If the smi-smi operation results in a smi return is generated. 1811 // If the smi-smi operation results in a smi return is generated.
1811 BinaryOpStub_GenerateSmiSmiOperation(masm, op); 1812 BinaryOpStub_GenerateSmiSmiOperation(masm, op, scratch1, scratch2);
1812 1813
1813 // If heap number results are possible generate the result in an allocated 1814 // If heap number results are possible generate the result in an allocated
1814 // heap number. 1815 // heap number.
1815 if (allow_heapnumber_results == BinaryOpStub::ALLOW_HEAPNUMBER_RESULTS) { 1816 if (allow_heapnumber_results == BinaryOpStub::ALLOW_HEAPNUMBER_RESULTS) {
1816 BinaryOpStub_GenerateFPOperation( 1817 BinaryOpStub_GenerateFPOperation(
1817 masm, BinaryOpIC::UNINITIALIZED, BinaryOpIC::UNINITIALIZED, true, 1818 masm, BinaryOpIC::UNINITIALIZED, BinaryOpIC::UNINITIALIZED, true,
1818 use_runtime, gc_required, &not_smis, op, mode); 1819 use_runtime, gc_required, &not_smis, op, mode, r6, r4, r5, r9);
JF 2013/07/29 17:20:09 It may be more readable to mark the last 4 argumen
rmcilroy 2013/07/30 11:39:44 I added them as scratch register arguments, which
1819 } 1820 }
1820 __ bind(&not_smis); 1821 __ bind(&not_smis);
1821 } 1822 }
1822 1823
1823 1824
1824 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 1825 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
1825 Label right_arg_changed, call_runtime; 1826 Label right_arg_changed, call_runtime;
1826 1827
1827 if (op_ == Token::MOD && encoded_right_arg_.has_value) { 1828 if (op_ == Token::MOD && encoded_right_arg_.has_value) {
1828 // It is guaranteed that the value will fit into a Smi, because if it 1829 // It is guaranteed that the value will fit into a Smi, because if it
1829 // didn't, we wouldn't be here, see BinaryOp_Patch. 1830 // didn't, we wouldn't be here, see BinaryOp_Patch.
1830 __ cmp(r0, Operand(Smi::FromInt(fixed_right_arg_value()))); 1831 __ cmp(r0, Operand(Smi::FromInt(fixed_right_arg_value())));
1831 __ b(ne, &right_arg_changed); 1832 __ b(ne, &right_arg_changed);
1832 } 1833 }
1833 1834
1834 if (result_type_ == BinaryOpIC::UNINITIALIZED || 1835 if (result_type_ == BinaryOpIC::UNINITIALIZED ||
1835 result_type_ == BinaryOpIC::SMI) { 1836 result_type_ == BinaryOpIC::SMI) {
1836 // Only allow smi results. 1837 // Only allow smi results.
1837 BinaryOpStub_GenerateSmiCode( 1838 BinaryOpStub_GenerateSmiCode(
1838 masm, &call_runtime, NULL, op_, NO_HEAPNUMBER_RESULTS, mode_); 1839 masm, &call_runtime, NULL, op_, NO_HEAPNUMBER_RESULTS, mode_, r5, r6);
1839 } else { 1840 } else {
1840 // Allow heap number result and don't make a transition if a heap number 1841 // Allow heap number result and don't make a transition if a heap number
1841 // cannot be allocated. 1842 // cannot be allocated.
1842 BinaryOpStub_GenerateSmiCode( 1843 BinaryOpStub_GenerateSmiCode(
1843 masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS, 1844 masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS,
1844 mode_); 1845 mode_, r5, r6);
1845 } 1846 }
1846 1847
1847 // Code falls through if the result is not returned as either a smi or heap 1848 // Code falls through if the result is not returned as either a smi or heap
1848 // number. 1849 // number.
1849 __ bind(&right_arg_changed); 1850 __ bind(&right_arg_changed);
1850 GenerateTypeTransition(masm); 1851 GenerateTypeTransition(masm);
1851 1852
1852 __ bind(&call_runtime); 1853 __ bind(&call_runtime);
1853 { 1854 {
1854 FrameScope scope(masm, StackFrame::INTERNAL); 1855 FrameScope scope(masm, StackFrame::INTERNAL);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1888 __ bind(&call_runtime); 1889 __ bind(&call_runtime);
1889 GenerateTypeTransition(masm); 1890 GenerateTypeTransition(masm);
1890 } 1891 }
1891 1892
1892 1893
1893 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { 1894 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
1894 ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32); 1895 ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32);
1895 1896
1896 Register left = r1; 1897 Register left = r1;
1897 Register right = r0; 1898 Register right = r0;
1898 Register scratch1 = r7; 1899 Register scratch1 = r4;
1899 Register scratch2 = r9; 1900 Register scratch2 = r9;
1901 Register scratch3 = r5;
1900 DwVfpRegister double_scratch = d0; 1902 DwVfpRegister double_scratch = d0;
1901 1903
1902 Register heap_number_result = no_reg; 1904 Register heap_number_result = no_reg;
1903 Register heap_number_map = r6; 1905 Register heap_number_map = r6;
1904 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 1906 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
1905 1907
1906 Label call_runtime; 1908 Label call_runtime;
1907 // Labels for type transition, used for wrong input or output types. 1909 // Labels for type transition, used for wrong input or output types.
1908 // Both label are currently actually bound to the same position. We use two 1910 // Both label are currently actually bound to the same position. We use two
1909 // different label to differentiate the cause leading to type transition. 1911 // different label to differentiate the cause leading to type transition.
1910 Label transition; 1912 Label transition;
1911 1913
1912 // Smi-smi fast case. 1914 // Smi-smi fast case.
1913 Label skip; 1915 Label skip;
1914 __ orr(scratch1, left, right); 1916 __ orr(scratch1, left, right);
1915 __ JumpIfNotSmi(scratch1, &skip); 1917 __ JumpIfNotSmi(scratch1, &skip);
1916 BinaryOpStub_GenerateSmiSmiOperation(masm, op_); 1918 BinaryOpStub_GenerateSmiSmiOperation(masm, op_, scratch2, scratch3);
1917 // Fall through if the result is not a smi. 1919 // Fall through if the result is not a smi.
1918 __ bind(&skip); 1920 __ bind(&skip);
1919 1921
1920 switch (op_) { 1922 switch (op_) {
1921 case Token::ADD: 1923 case Token::ADD:
1922 case Token::SUB: 1924 case Token::SUB:
1923 case Token::MUL: 1925 case Token::MUL:
1924 case Token::DIV: 1926 case Token::DIV:
1925 case Token::MOD: { 1927 case Token::MOD: {
1926 // It could be that only SMIs have been seen at either the left 1928 // It could be that only SMIs have been seen at either the left
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
2000 // A DIV operation expecting an integer result falls through 2002 // A DIV operation expecting an integer result falls through
2001 // to type transition. 2003 // to type transition.
2002 2004
2003 } else { 2005 } else {
2004 if (encoded_right_arg_.has_value) { 2006 if (encoded_right_arg_.has_value) {
2005 __ Vmov(d8, fixed_right_arg_value(), scratch1); 2007 __ Vmov(d8, fixed_right_arg_value(), scratch1);
2006 __ VFPCompareAndSetFlags(d1, d8); 2008 __ VFPCompareAndSetFlags(d1, d8);
2007 __ b(ne, &transition); 2009 __ b(ne, &transition);
2008 } 2010 }
2009 2011
2010 // We preserved r0 and r1 to be able to call runtime.
2011 // Save the left value on the stack.
2012 __ Push(r5, r4);
rmcilroy 2013/07/29 12:06:53 I'm not sure what this push, and the subsequent po
ulan 2013/07/30 09:45:19 Yes, I think the pushes and pops are redundant.
rmcilroy 2013/07/30 11:39:44 Ack
2013
2014 Label pop_and_call_runtime;
2015
2016 // Allocate a heap number to store the result. 2012 // Allocate a heap number to store the result.
2017 heap_number_result = r5; 2013 heap_number_result = r5;
2018 BinaryOpStub_GenerateHeapResultAllocation(masm, 2014 BinaryOpStub_GenerateHeapResultAllocation(masm,
2019 heap_number_result, 2015 heap_number_result,
2020 heap_number_map, 2016 heap_number_map,
2021 scratch1, 2017 scratch1,
2022 scratch2, 2018 scratch2,
2023 &pop_and_call_runtime, 2019 &call_runtime,
2024 mode_); 2020 mode_);
2025 2021
2026 // Load the left value from the value saved on the stack.
2027 __ Pop(r1, r0);
2028
2029 // Call the C function to handle the double operation. 2022 // Call the C function to handle the double operation.
2030 CallCCodeForDoubleOperation(masm, op_, heap_number_result, scratch1); 2023 CallCCodeForDoubleOperation(masm, op_, heap_number_result, scratch1);
2031 if (FLAG_debug_code) { 2024 if (FLAG_debug_code) {
2032 __ stop("Unreachable code."); 2025 __ stop("Unreachable code.");
2033 } 2026 }
2034 2027
2035 __ bind(&pop_and_call_runtime);
2036 __ Drop(2);
2037 __ b(&call_runtime); 2028 __ b(&call_runtime);
2038 } 2029 }
2039 2030
2040 break; 2031 break;
2041 } 2032 }
2042 2033
2043 case Token::BIT_OR: 2034 case Token::BIT_OR:
2044 case Token::BIT_XOR: 2035 case Token::BIT_XOR:
2045 case Token::BIT_AND: 2036 case Token::BIT_AND:
2046 case Token::SAR: 2037 case Token::SAR:
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
2177 __ bind(&done); 2168 __ bind(&done);
2178 2169
2179 GenerateNumberStub(masm); 2170 GenerateNumberStub(masm);
2180 } 2171 }
2181 2172
2182 2173
2183 void BinaryOpStub::GenerateNumberStub(MacroAssembler* masm) { 2174 void BinaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
2184 Label call_runtime, transition; 2175 Label call_runtime, transition;
2185 BinaryOpStub_GenerateFPOperation( 2176 BinaryOpStub_GenerateFPOperation(
2186 masm, left_type_, right_type_, false, 2177 masm, left_type_, right_type_, false,
2187 &transition, &call_runtime, &transition, op_, mode_); 2178 &transition, &call_runtime, &transition, op_, mode_, r6, r4, r5, r9);
2188 2179
2189 __ bind(&transition); 2180 __ bind(&transition);
2190 GenerateTypeTransition(masm); 2181 GenerateTypeTransition(masm);
2191 2182
2192 __ bind(&call_runtime); 2183 __ bind(&call_runtime);
2193 { 2184 {
2194 FrameScope scope(masm, StackFrame::INTERNAL); 2185 FrameScope scope(masm, StackFrame::INTERNAL);
2195 GenerateRegisterArgsPush(masm); 2186 GenerateRegisterArgsPush(masm);
2196 GenerateCallRuntime(masm); 2187 GenerateCallRuntime(masm);
2197 } 2188 }
2198 __ Ret(); 2189 __ Ret();
2199 } 2190 }
2200 2191
2201 2192
2202 void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) { 2193 void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
2203 Label call_runtime, call_string_add_or_runtime, transition; 2194 Label call_runtime, call_string_add_or_runtime, transition;
2204 2195
2205 BinaryOpStub_GenerateSmiCode( 2196 BinaryOpStub_GenerateSmiCode(
2206 masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS, mode_); 2197 masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS, mode_,
2198 r5, r6);
2207 2199
2208 BinaryOpStub_GenerateFPOperation( 2200 BinaryOpStub_GenerateFPOperation(
2209 masm, left_type_, right_type_, false, 2201 masm, left_type_, right_type_, false,
2210 &call_string_add_or_runtime, &call_runtime, &transition, op_, mode_); 2202 &call_string_add_or_runtime, &call_runtime, &transition, op_, mode_, r6,
2203 r4, r5, r9);
2211 2204
2212 __ bind(&transition); 2205 __ bind(&transition);
2213 GenerateTypeTransition(masm); 2206 GenerateTypeTransition(masm);
2214 2207
2215 __ bind(&call_string_add_or_runtime); 2208 __ bind(&call_string_add_or_runtime);
2216 if (op_ == Token::ADD) { 2209 if (op_ == Token::ADD) {
2217 GenerateAddStrings(masm); 2210 GenerateAddStrings(masm);
2218 } 2211 }
2219 2212
2220 __ bind(&call_runtime); 2213 __ bind(&call_runtime);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
2302 // Untagged case: double input in d2, double result goes 2295 // Untagged case: double input in d2, double result goes
2303 // into d2. 2296 // into d2.
2304 // Tagged case: tagged input on top of stack and in r0, 2297 // Tagged case: tagged input on top of stack and in r0,
2305 // tagged result (heap number) goes into r0. 2298 // tagged result (heap number) goes into r0.
2306 2299
2307 Label input_not_smi; 2300 Label input_not_smi;
2308 Label loaded; 2301 Label loaded;
2309 Label calculate; 2302 Label calculate;
2310 Label invalid_cache; 2303 Label invalid_cache;
2311 const Register scratch0 = r9; 2304 const Register scratch0 = r9;
2312 const Register scratch1 = r7; 2305 const Register scratch1 = r4;
2313 const Register cache_entry = r0; 2306 const Register cache_entry = r0;
2314 const bool tagged = (argument_type_ == TAGGED); 2307 const bool tagged = (argument_type_ == TAGGED);
2315 2308
2316 if (tagged) { 2309 if (tagged) {
2317 // Argument is a number and is on stack and in r0. 2310 // Argument is a number and is on stack and in r0.
2318 // Load argument and check if it is a smi. 2311 // Load argument and check if it is a smi.
2319 __ JumpIfNotSmi(r0, &input_not_smi); 2312 __ JumpIfNotSmi(r0, &input_not_smi);
2320 2313
2321 // Input is a smi. Convert to double and load the low and high words 2314 // Input is a smi. Convert to double and load the low and high words
2322 // of the double into r2, r3. 2315 // of the double into r2, r3.
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
2534 const Register base = r1; 2527 const Register base = r1;
2535 const Register exponent = r2; 2528 const Register exponent = r2;
2536 const Register heapnumbermap = r5; 2529 const Register heapnumbermap = r5;
2537 const Register heapnumber = r0; 2530 const Register heapnumber = r0;
2538 const DwVfpRegister double_base = d1; 2531 const DwVfpRegister double_base = d1;
2539 const DwVfpRegister double_exponent = d2; 2532 const DwVfpRegister double_exponent = d2;
2540 const DwVfpRegister double_result = d3; 2533 const DwVfpRegister double_result = d3;
2541 const DwVfpRegister double_scratch = d0; 2534 const DwVfpRegister double_scratch = d0;
2542 const SwVfpRegister single_scratch = s0; 2535 const SwVfpRegister single_scratch = s0;
2543 const Register scratch = r9; 2536 const Register scratch = r9;
2544 const Register scratch2 = r7; 2537 const Register scratch2 = r4;
2545 2538
2546 Label call_runtime, done, int_exponent; 2539 Label call_runtime, done, int_exponent;
2547 if (exponent_type_ == ON_STACK) { 2540 if (exponent_type_ == ON_STACK) {
2548 Label base_is_smi, unpack_exponent; 2541 Label base_is_smi, unpack_exponent;
2549 // The exponent and base are supplied as arguments on the stack. 2542 // The exponent and base are supplied as arguments on the stack.
2550 // This can only happen if the stub is called from non-optimized code. 2543 // This can only happen if the stub is called from non-optimized code.
2551 // Load input parameters from stack to double registers. 2544 // Load input parameters from stack to double registers.
2552 __ ldr(base, MemOperand(sp, 1 * kPointerSize)); 2545 __ ldr(base, MemOperand(sp, 1 * kPointerSize));
2553 __ ldr(exponent, MemOperand(sp, 0 * kPointerSize)); 2546 __ ldr(exponent, MemOperand(sp, 0 * kPointerSize));
2554 2547
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
3043 offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize; 3036 offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize;
3044 __ ldr(r4, MemOperand(sp, offset_to_argv)); 3037 __ ldr(r4, MemOperand(sp, offset_to_argv));
3045 3038
3046 // Push a frame with special values setup to mark it as an entry frame. 3039 // Push a frame with special values setup to mark it as an entry frame.
3047 // r0: code entry 3040 // r0: code entry
3048 // r1: function 3041 // r1: function
3049 // r2: receiver 3042 // r2: receiver
3050 // r3: argc 3043 // r3: argc
3051 // r4: argv 3044 // r4: argv
3052 Isolate* isolate = masm->isolate(); 3045 Isolate* isolate = masm->isolate();
3053 __ mov(r8, Operand(-1)); // Push a bad frame pointer to fail if it is used. 3046 __ mov(ip, Operand(-1)); // Push a bad frame pointer to fail if it is used.
ulan 2013/07/30 09:45:19 Move it down to the usage line, otherwise ip might
rmcilroy 2013/07/30 11:39:44 Done.
3054 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; 3047 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
3055 __ mov(r7, Operand(Smi::FromInt(marker))); 3048 __ mov(r8, Operand(Smi::FromInt(marker)));
3056 __ mov(r6, Operand(Smi::FromInt(marker))); 3049 __ mov(r6, Operand(Smi::FromInt(marker)));
3057 __ mov(r5, 3050 __ mov(r5,
3058 Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate))); 3051 Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate)));
3059 __ ldr(r5, MemOperand(r5)); 3052 __ ldr(r5, MemOperand(r5));
3060 __ Push(r8, r7, r6, r5); 3053 __ Push(ip, r8, r6, r5);
3061 3054
3062 // Set up frame pointer for the frame to be pushed. 3055 // Set up frame pointer for the frame to be pushed.
3063 __ add(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); 3056 __ add(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
3064 3057
3065 // If this is the outermost JS call, set js_entry_sp value. 3058 // If this is the outermost JS call, set js_entry_sp value.
3066 Label non_outermost_js; 3059 Label non_outermost_js;
3067 ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate); 3060 ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate);
3068 __ mov(r5, Operand(ExternalReference(js_entry_sp))); 3061 __ mov(r5, Operand(ExternalReference(js_entry_sp)));
3069 __ ldr(r6, MemOperand(r5)); 3062 __ ldr(r6, MemOperand(r5));
3070 __ cmp(r6, Operand::Zero()); 3063 __ cmp(r6, Operand::Zero());
(...skipping 25 matching lines...) Expand all
3096 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 3089 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
3097 isolate))); 3090 isolate)));
3098 } 3091 }
3099 __ str(r0, MemOperand(ip)); 3092 __ str(r0, MemOperand(ip));
3100 __ mov(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception()))); 3093 __ mov(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
3101 __ b(&exit); 3094 __ b(&exit);
3102 3095
3103 // Invoke: Link this frame into the handler chain. There's only one 3096 // Invoke: Link this frame into the handler chain. There's only one
3104 // handler block in this code object, so its index is 0. 3097 // handler block in this code object, so its index is 0.
3105 __ bind(&invoke); 3098 __ bind(&invoke);
3106 // Must preserve r0-r4, r5-r7 are available. 3099 // Must preserve r0-r4, r5-r6 are available.
3107 __ PushTryHandler(StackHandler::JS_ENTRY, 0); 3100 __ PushTryHandler(StackHandler::JS_ENTRY, 0);
3108 // If an exception not caught by another handler occurs, this handler 3101 // If an exception not caught by another handler occurs, this handler
3109 // returns control to the code after the bl(&invoke) above, which 3102 // returns control to the code after the bl(&invoke) above, which
3110 // restores all kCalleeSaved registers (including cp and fp) to their 3103 // restores all kCalleeSaved registers (including cp and fp) to their
3111 // saved values before returning a failure to C. 3104 // saved values before returning a failure to C.
3112 3105
3113 // Clear any pending exceptions. 3106 // Clear any pending exceptions.
3114 __ mov(r5, Operand(isolate->factory()->the_hole_value())); 3107 __ mov(r5, Operand(isolate->factory()->the_hole_value()));
3115 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 3108 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
3116 isolate))); 3109 isolate)));
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
3704 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 3697 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
3705 // The mapped parameter thus need to get indices 3698 // The mapped parameter thus need to get indices
3706 // MIN_CONTEXT_SLOTS+parameter_count-1 .. 3699 // MIN_CONTEXT_SLOTS+parameter_count-1 ..
3707 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count 3700 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
3708 // We loop from right to left. 3701 // We loop from right to left.
3709 Label parameters_loop, parameters_test; 3702 Label parameters_loop, parameters_test;
3710 __ mov(r6, r1); 3703 __ mov(r6, r1);
3711 __ ldr(r9, MemOperand(sp, 0 * kPointerSize)); 3704 __ ldr(r9, MemOperand(sp, 0 * kPointerSize));
3712 __ add(r9, r9, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); 3705 __ add(r9, r9, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
3713 __ sub(r9, r9, Operand(r1)); 3706 __ sub(r9, r9, Operand(r1));
3714 __ LoadRoot(r7, Heap::kTheHoleValueRootIndex); 3707 __ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
3715 __ add(r3, r4, Operand(r6, LSL, 1)); 3708 __ add(r3, r4, Operand(r6, LSL, 1));
3716 __ add(r3, r3, Operand(kParameterMapHeaderSize)); 3709 __ add(r3, r3, Operand(kParameterMapHeaderSize));
3717 3710
3718 // r6 = loop variable (tagged) 3711 // r6 = loop variable (tagged)
3719 // r1 = mapping index (tagged) 3712 // r1 = mapping index (tagged)
3720 // r3 = address of backing store (tagged) 3713 // r3 = address of backing store (tagged)
3721 // r4 = address of parameter map (tagged) 3714 // r4 = address of parameter map (tagged)
3722 // r5 = temporary scratch (a.o., for address calculation) 3715 // ip = temporary scratch (a.o., for address calculation)
ulan 2013/07/30 09:45:19 This is fragile.
rmcilroy 2013/07/30 11:39:44 Replaced use of ip with r0 (and restore r0 after l
3723 // r7 = the hole value 3716 // r5 = the hole value
3724 __ jmp(&parameters_test); 3717 __ jmp(&parameters_test);
3725 3718
3726 __ bind(&parameters_loop); 3719 __ bind(&parameters_loop);
3727 __ sub(r6, r6, Operand(Smi::FromInt(1))); 3720 __ sub(r6, r6, Operand(Smi::FromInt(1)));
3728 __ mov(r5, Operand(r6, LSL, 1)); 3721 __ mov(ip, Operand(r6, LSL, 1));
3729 __ add(r5, r5, Operand(kParameterMapHeaderSize - kHeapObjectTag)); 3722 __ add(ip, ip, Operand(kParameterMapHeaderSize - kHeapObjectTag));
3730 __ str(r9, MemOperand(r4, r5)); 3723 __ str(r9, MemOperand(r4, ip));
3731 __ sub(r5, r5, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize)); 3724 __ sub(ip, ip, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
3732 __ str(r7, MemOperand(r3, r5)); 3725 __ str(r5, MemOperand(r3, ip));
3733 __ add(r9, r9, Operand(Smi::FromInt(1))); 3726 __ add(r9, r9, Operand(Smi::FromInt(1)));
3734 __ bind(&parameters_test); 3727 __ bind(&parameters_test);
3735 __ cmp(r6, Operand(Smi::FromInt(0))); 3728 __ cmp(r6, Operand(Smi::FromInt(0)));
3736 __ b(ne, &parameters_loop); 3729 __ b(ne, &parameters_loop);
3737 3730
3738 __ bind(&skip_parameter_map); 3731 __ bind(&skip_parameter_map);
3739 // r2 = argument count (tagged) 3732 // r2 = argument count (tagged)
3740 // r3 = address of backing store (tagged) 3733 // r3 = address of backing store (tagged)
3741 // r5 = scratch 3734 // r5 = scratch
3742 // Copy arguments header and remaining slots (if there are any). 3735 // Copy arguments header and remaining slots (if there are any).
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
3887 const int kJSRegExpOffset = 3 * kPointerSize; 3880 const int kJSRegExpOffset = 3 * kPointerSize;
3888 3881
3889 Label runtime; 3882 Label runtime;
3890 // Allocation of registers for this function. These are in callee save 3883 // Allocation of registers for this function. These are in callee save
3891 // registers and will be preserved by the call to the native RegExp code, as 3884 // registers and will be preserved by the call to the native RegExp code, as
3892 // this code is called using the normal C calling convention. When calling 3885 // this code is called using the normal C calling convention. When calling
3893 // directly from generated code the native RegExp code will not do a GC and 3886 // directly from generated code the native RegExp code will not do a GC and
3894 // therefore the content of these registers are safe to use after the call. 3887 // therefore the content of these registers are safe to use after the call.
3895 Register subject = r4; 3888 Register subject = r4;
3896 Register regexp_data = r5; 3889 Register regexp_data = r5;
3897 Register last_match_info_elements = r6; 3890 Register last_match_info_elements = no_reg; // will be r6;
3898 3891
3899 // Ensure that a RegExp stack is allocated. 3892 // Ensure that a RegExp stack is allocated.
3900 Isolate* isolate = masm->isolate(); 3893 Isolate* isolate = masm->isolate();
3901 ExternalReference address_of_regexp_stack_memory_address = 3894 ExternalReference address_of_regexp_stack_memory_address =
3902 ExternalReference::address_of_regexp_stack_memory_address(isolate); 3895 ExternalReference::address_of_regexp_stack_memory_address(isolate);
3903 ExternalReference address_of_regexp_stack_memory_size = 3896 ExternalReference address_of_regexp_stack_memory_size =
3904 ExternalReference::address_of_regexp_stack_memory_size(isolate); 3897 ExternalReference::address_of_regexp_stack_memory_size(isolate);
3905 __ mov(r0, Operand(address_of_regexp_stack_memory_size)); 3898 __ mov(r0, Operand(address_of_regexp_stack_memory_size));
3906 __ ldr(r0, MemOperand(r0, 0)); 3899 __ ldr(r0, MemOperand(r0, 0));
3907 __ cmp(r0, Operand::Zero()); 3900 __ cmp(r0, Operand::Zero());
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
4020 __ JumpIfNotSmi(r1, &runtime); 4013 __ JumpIfNotSmi(r1, &runtime);
4021 __ ldr(r3, FieldMemOperand(r3, String::kLengthOffset)); 4014 __ ldr(r3, FieldMemOperand(r3, String::kLengthOffset));
4022 __ cmp(r3, Operand(r1)); 4015 __ cmp(r3, Operand(r1));
4023 __ b(ls, &runtime); 4016 __ b(ls, &runtime);
4024 __ SmiUntag(r1); 4017 __ SmiUntag(r1);
4025 4018
4026 STATIC_ASSERT(4 == kOneByteStringTag); 4019 STATIC_ASSERT(4 == kOneByteStringTag);
4027 STATIC_ASSERT(kTwoByteStringTag == 0); 4020 STATIC_ASSERT(kTwoByteStringTag == 0);
4028 __ and_(r0, r0, Operand(kStringEncodingMask)); 4021 __ and_(r0, r0, Operand(kStringEncodingMask));
4029 __ mov(r3, Operand(r0, ASR, 2), SetCC); 4022 __ mov(r3, Operand(r0, ASR, 2), SetCC);
4030 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); 4023 __ ldr(r6, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne);
4031 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq); 4024 __ ldr(r6, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq);
4032 4025
4033 // (E) Carry on. String handling is done. 4026 // (E) Carry on. String handling is done.
4034 // r7: irregexp code 4027 // r6: irregexp code
4035 // Check that the irregexp code has been generated for the actual string 4028 // Check that the irregexp code has been generated for the actual string
4036 // encoding. If it has, the field contains a code object otherwise it contains 4029 // encoding. If it has, the field contains a code object otherwise it contains
4037 // a smi (code flushing support). 4030 // a smi (code flushing support).
4038 __ JumpIfSmi(r7, &runtime); 4031 __ JumpIfSmi(r6, &runtime);
4039 4032
4040 // r1: previous index 4033 // r1: previous index
4041 // r3: encoding of subject string (1 if ASCII, 0 if two_byte); 4034 // r3: encoding of subject string (1 if ASCII, 0 if two_byte);
4042 // r7: code 4035 // r6: code
4043 // subject: Subject string 4036 // subject: Subject string
4044 // regexp_data: RegExp data (FixedArray) 4037 // regexp_data: RegExp data (FixedArray)
4045 // All checks done. Now push arguments for native regexp code. 4038 // All checks done. Now push arguments for native regexp code.
4046 __ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r0, r2); 4039 __ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r0, r2);
4047 4040
4048 // Isolates: note we add an additional parameter here (isolate pointer). 4041 // Isolates: note we add an additional parameter here (isolate pointer).
4049 const int kRegExpExecuteArguments = 9; 4042 const int kRegExpExecuteArguments = 9;
4050 const int kParameterRegisters = 4; 4043 const int kParameterRegisters = 4;
4051 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); 4044 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
4052 4045
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
4099 __ SmiUntag(r8); 4092 __ SmiUntag(r8);
4100 __ add(r3, r9, Operand(r8, LSL, r3)); 4093 __ add(r3, r9, Operand(r8, LSL, r3));
4101 4094
4102 // Argument 2 (r1): Previous index. 4095 // Argument 2 (r1): Previous index.
4103 // Already there 4096 // Already there
4104 4097
4105 // Argument 1 (r0): Subject string. 4098 // Argument 1 (r0): Subject string.
4106 __ mov(r0, subject); 4099 __ mov(r0, subject);
4107 4100
4108 // Locate the code entry and call it. 4101 // Locate the code entry and call it.
4109 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); 4102 __ add(r6, r6, Operand(Code::kHeaderSize - kHeapObjectTag));
4110 DirectCEntryStub stub; 4103 DirectCEntryStub stub;
4111 stub.GenerateCall(masm, r7); 4104 stub.GenerateCall(masm, r6);
4112 4105
4113 __ LeaveExitFrame(false, no_reg); 4106 __ LeaveExitFrame(false, no_reg);
4114 4107
4108 last_match_info_elements = r6;
4109
4115 // r0: result 4110 // r0: result
4116 // subject: subject string (callee saved) 4111 // subject: subject string (callee saved)
4117 // regexp_data: RegExp data (callee saved) 4112 // regexp_data: RegExp data (callee saved)
4118 // last_match_info_elements: Last match info elements (callee saved) 4113 // last_match_info_elements: Last match info elements (callee saved)
4119 // Check the result. 4114 // Check the result.
4120 Label success; 4115 Label success;
4121 __ cmp(r0, Operand(1)); 4116 __ cmp(r0, Operand(1));
4122 // We expect exactly one result since we force the called regexp to behave 4117 // We expect exactly one result since we force the called regexp to behave
4123 // as non-global. 4118 // as non-global.
4124 __ b(eq, &success); 4119 __ b(eq, &success);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
4193 __ str(r2, FieldMemOperand(last_match_info_elements, 4188 __ str(r2, FieldMemOperand(last_match_info_elements,
4194 RegExpImpl::kLastCaptureCountOffset)); 4189 RegExpImpl::kLastCaptureCountOffset));
4195 // Store last subject and last input. 4190 // Store last subject and last input.
4196 __ str(subject, 4191 __ str(subject,
4197 FieldMemOperand(last_match_info_elements, 4192 FieldMemOperand(last_match_info_elements,
4198 RegExpImpl::kLastSubjectOffset)); 4193 RegExpImpl::kLastSubjectOffset));
4199 __ mov(r2, subject); 4194 __ mov(r2, subject);
4200 __ RecordWriteField(last_match_info_elements, 4195 __ RecordWriteField(last_match_info_elements,
4201 RegExpImpl::kLastSubjectOffset, 4196 RegExpImpl::kLastSubjectOffset,
4202 subject, 4197 subject,
4203 r7, 4198 r3,
4204 kLRHasNotBeenSaved, 4199 kLRHasNotBeenSaved,
4205 kDontSaveFPRegs); 4200 kDontSaveFPRegs);
4206 __ mov(subject, r2); 4201 __ mov(subject, r2);
4207 __ str(subject, 4202 __ str(subject,
4208 FieldMemOperand(last_match_info_elements, 4203 FieldMemOperand(last_match_info_elements,
4209 RegExpImpl::kLastInputOffset)); 4204 RegExpImpl::kLastInputOffset));
4210 __ RecordWriteField(last_match_info_elements, 4205 __ RecordWriteField(last_match_info_elements,
4211 RegExpImpl::kLastInputOffset, 4206 RegExpImpl::kLastInputOffset,
4212 subject, 4207 subject,
4213 r7, 4208 r3,
4214 kLRHasNotBeenSaved, 4209 kLRHasNotBeenSaved,
4215 kDontSaveFPRegs); 4210 kDontSaveFPRegs);
4216 4211
4217 // Get the static offsets vector filled by the native regexp code. 4212 // Get the static offsets vector filled by the native regexp code.
4218 ExternalReference address_of_static_offsets_vector = 4213 ExternalReference address_of_static_offsets_vector =
4219 ExternalReference::address_of_static_offsets_vector(isolate); 4214 ExternalReference::address_of_static_offsets_vector(isolate);
4220 __ mov(r2, Operand(address_of_static_offsets_vector)); 4215 __ mov(r2, Operand(address_of_static_offsets_vector));
4221 4216
4222 // r1: number of capture registers 4217 // r1: number of capture registers
4223 // r2: offsets vector 4218 // r2: offsets vector
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after
4769 4764
4770 4765
4771 void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm, 4766 void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
4772 Register dest, 4767 Register dest,
4773 Register src, 4768 Register src,
4774 Register count, 4769 Register count,
4775 Register scratch1, 4770 Register scratch1,
4776 Register scratch2, 4771 Register scratch2,
4777 Register scratch3, 4772 Register scratch3,
4778 Register scratch4, 4773 Register scratch4,
4779 Register scratch5,
4780 int flags) { 4774 int flags) {
4781 bool ascii = (flags & COPY_ASCII) != 0; 4775 bool ascii = (flags & COPY_ASCII) != 0;
4782 bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0; 4776 bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0;
4783 4777
4784 if (dest_always_aligned && FLAG_debug_code) { 4778 if (dest_always_aligned && FLAG_debug_code) {
4785 // Check that destination is actually word aligned if the flag says 4779 // Check that destination is actually word aligned if the flag says
4786 // that it is. 4780 // that it is.
4787 __ tst(dest, Operand(kPointerAlignmentMask)); 4781 __ tst(dest, Operand(kPointerAlignmentMask));
4788 __ Check(eq, "Destination of copy not aligned."); 4782 __ Check(eq, "Destination of copy not aligned.");
4789 } 4783 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
4844 __ and_(src, src, Operand(~3)); // Round down to load previous word. 4838 __ and_(src, src, Operand(~3)); // Round down to load previous word.
4845 __ ldr(scratch1, MemOperand(src, 4, PostIndex)); 4839 __ ldr(scratch1, MemOperand(src, 4, PostIndex));
4846 // Store the "shift" most significant bits of scratch in the least 4840 // Store the "shift" most significant bits of scratch in the least
4847 // signficant bits (i.e., shift down by (32-shift)). 4841 // signficant bits (i.e., shift down by (32-shift)).
4848 __ rsb(scratch2, left_shift, Operand(32)); 4842 __ rsb(scratch2, left_shift, Operand(32));
4849 Register right_shift = scratch2; 4843 Register right_shift = scratch2;
4850 __ mov(scratch1, Operand(scratch1, LSR, right_shift)); 4844 __ mov(scratch1, Operand(scratch1, LSR, right_shift));
4851 4845
4852 __ bind(&loop); 4846 __ bind(&loop);
4853 __ ldr(scratch3, MemOperand(src, 4, PostIndex)); 4847 __ ldr(scratch3, MemOperand(src, 4, PostIndex));
4854 __ sub(scratch5, limit, Operand(dest));
4855 __ orr(scratch1, scratch1, Operand(scratch3, LSL, left_shift)); 4848 __ orr(scratch1, scratch1, Operand(scratch3, LSL, left_shift));
4856 __ str(scratch1, MemOperand(dest, 4, PostIndex)); 4849 __ str(scratch1, MemOperand(dest, 4, PostIndex));
4857 __ mov(scratch1, Operand(scratch3, LSR, right_shift)); 4850 __ mov(scratch1, Operand(scratch3, LSR, right_shift));
4858 // Loop if four or more bytes left to copy. 4851 // Loop if four or more bytes left to copy.
4859 // Compare to eight, because we did the subtract before increasing dst. 4852 __ sub(scratch3, limit, Operand(dest));
4860 __ sub(scratch5, scratch5, Operand(8), SetCC); 4853 __ sub(scratch3, scratch3, Operand(4), SetCC);
4861 __ b(ge, &loop); 4854 __ b(ge, &loop);
4862 } 4855 }
4863 // There is now between zero and three bytes left to copy (negative that 4856 // There is now between zero and three bytes left to copy (negative that
4864 // number is in scratch5), and between one and three bytes already read into 4857 // number is in scratch3), and between one and three bytes already read into
4865 // scratch1 (eight times that number in scratch4). We may have read past 4858 // scratch1 (eight times that number in scratch4). We may have read past
4866 // the end of the string, but because objects are aligned, we have not read 4859 // the end of the string, but because objects are aligned, we have not read
4867 // past the end of the object. 4860 // past the end of the object.
4868 // Find the minimum of remaining characters to move and preloaded characters 4861 // Find the minimum of remaining characters to move and preloaded characters
4869 // and write those as bytes. 4862 // and write those as bytes.
4870 __ add(scratch5, scratch5, Operand(4), SetCC); 4863 __ add(scratch3, scratch3, Operand(4), SetCC);
4871 __ b(eq, &done); 4864 __ b(eq, &done);
4872 __ cmp(scratch4, Operand(scratch5, LSL, 3), ne); 4865 __ cmp(scratch4, Operand(scratch3, LSL, 3), ne);
4873 // Move minimum of bytes read and bytes left to copy to scratch4. 4866 // Move minimum of bytes read and bytes left to copy to scratch4.
4874 __ mov(scratch5, Operand(scratch4, LSR, 3), LeaveCC, lt); 4867 __ mov(scratch3, Operand(scratch4, LSR, 3), LeaveCC, lt);
4875 // Between one and three (value in scratch5) characters already read into 4868 // Between one and three (value in scratch3) characters already read into
4876 // scratch ready to write. 4869 // scratch ready to write.
4877 __ cmp(scratch5, Operand(2)); 4870 __ cmp(scratch3, Operand(2));
4878 __ strb(scratch1, MemOperand(dest, 1, PostIndex)); 4871 __ strb(scratch1, MemOperand(dest, 1, PostIndex));
4879 __ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, ge); 4872 __ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, ge);
4880 __ strb(scratch1, MemOperand(dest, 1, PostIndex), ge); 4873 __ strb(scratch1, MemOperand(dest, 1, PostIndex), ge);
4881 __ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, gt); 4874 __ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, gt);
4882 __ strb(scratch1, MemOperand(dest, 1, PostIndex), gt); 4875 __ strb(scratch1, MemOperand(dest, 1, PostIndex), gt);
4883 // Copy any remaining bytes. 4876 // Copy any remaining bytes.
4884 __ b(&byte_loop); 4877 __ b(&byte_loop);
4885 4878
4886 // Simple loop. 4879 // Simple loop.
4887 // Copy words from src to dst, until less than four bytes left. 4880 // Copy words from src to dst, until less than four bytes left.
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
5207 // Allocate new sliced string. At this point we do not reload the instance 5200 // Allocate new sliced string. At this point we do not reload the instance
5208 // type including the string encoding because we simply rely on the info 5201 // type including the string encoding because we simply rely on the info
5209 // provided by the original string. It does not matter if the original 5202 // provided by the original string. It does not matter if the original
5210 // string's encoding is wrong because we always have to recheck encoding of 5203 // string's encoding is wrong because we always have to recheck encoding of
5211 // the newly created string's parent anyways due to externalized strings. 5204 // the newly created string's parent anyways due to externalized strings.
5212 Label two_byte_slice, set_slice_header; 5205 Label two_byte_slice, set_slice_header;
5213 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); 5206 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
5214 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 5207 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
5215 __ tst(r1, Operand(kStringEncodingMask)); 5208 __ tst(r1, Operand(kStringEncodingMask));
5216 __ b(eq, &two_byte_slice); 5209 __ b(eq, &two_byte_slice);
5217 __ AllocateAsciiSlicedString(r0, r2, r6, r7, &runtime); 5210 __ AllocateAsciiSlicedString(r0, r2, r6, r4, &runtime);
5218 __ jmp(&set_slice_header); 5211 __ jmp(&set_slice_header);
5219 __ bind(&two_byte_slice); 5212 __ bind(&two_byte_slice);
5220 __ AllocateTwoByteSlicedString(r0, r2, r6, r7, &runtime); 5213 __ AllocateTwoByteSlicedString(r0, r2, r6, r4, &runtime);
5221 __ bind(&set_slice_header); 5214 __ bind(&set_slice_header);
5222 __ mov(r3, Operand(r3, LSL, 1)); 5215 __ mov(r3, Operand(r3, LSL, 1));
5223 __ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); 5216 __ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset));
5224 __ str(r3, FieldMemOperand(r0, SlicedString::kOffsetOffset)); 5217 __ str(r3, FieldMemOperand(r0, SlicedString::kOffsetOffset));
5225 __ jmp(&return_r0); 5218 __ jmp(&return_r0);
5226 5219
5227 __ bind(&copy_routine); 5220 __ bind(&copy_routine);
5228 } 5221 }
5229 5222
5230 // r5: underlying subject string 5223 // r5: underlying subject string
(...skipping 20 matching lines...) Expand all
5251 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 5244 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
5252 __ add(r5, r5, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 5245 __ add(r5, r5, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
5253 5246
5254 __ bind(&allocate_result); 5247 __ bind(&allocate_result);
5255 // Sequential acii string. Allocate the result. 5248 // Sequential acii string. Allocate the result.
5256 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); 5249 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
5257 __ tst(r1, Operand(kStringEncodingMask)); 5250 __ tst(r1, Operand(kStringEncodingMask));
5258 __ b(eq, &two_byte_sequential); 5251 __ b(eq, &two_byte_sequential);
5259 5252
5260 // Allocate and copy the resulting ASCII string. 5253 // Allocate and copy the resulting ASCII string.
5261 __ AllocateAsciiString(r0, r2, r4, r6, r7, &runtime); 5254 __ AllocateAsciiString(r0, r2, r4, r6, r1, &runtime);
5262 5255
5263 // Locate first character of substring to copy. 5256 // Locate first character of substring to copy.
5264 __ add(r5, r5, r3); 5257 __ add(r5, r5, r3);
5265 // Locate first character of result. 5258 // Locate first character of result.
5266 __ add(r1, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 5259 __ add(r1, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
5267 5260
5268 // r0: result string 5261 // r0: result string
5269 // r1: first character of result string 5262 // r1: first character of result string
5270 // r2: result string length 5263 // r2: result string length
5271 // r5: first character of substring to copy 5264 // r5: first character of substring to copy
5272 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); 5265 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
5273 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, 5266 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r9,
5274 COPY_ASCII | DEST_ALWAYS_ALIGNED); 5267 COPY_ASCII | DEST_ALWAYS_ALIGNED);
5275 __ jmp(&return_r0); 5268 __ jmp(&return_r0);
5276 5269
5277 // Allocate and copy the resulting two-byte string. 5270 // Allocate and copy the resulting two-byte string.
5278 __ bind(&two_byte_sequential); 5271 __ bind(&two_byte_sequential);
5279 __ AllocateTwoByteString(r0, r2, r4, r6, r7, &runtime); 5272 __ AllocateTwoByteString(r0, r2, r4, r6, r1, &runtime);
5280 5273
5281 // Locate first character of substring to copy. 5274 // Locate first character of substring to copy.
5282 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 5275 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
5283 __ add(r5, r5, Operand(r3, LSL, 1)); 5276 __ add(r5, r5, Operand(r3, LSL, 1));
5284 // Locate first character of result. 5277 // Locate first character of result.
5285 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 5278 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
5286 5279
5287 // r0: result string. 5280 // r0: result string.
5288 // r1: first character of result. 5281 // r1: first character of result.
5289 // r2: result length. 5282 // r2: result length.
5290 // r5: first character of substring to copy. 5283 // r5: first character of substring to copy.
5291 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 5284 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
5292 StringHelper::GenerateCopyCharactersLong( 5285 StringHelper::GenerateCopyCharactersLong(
5293 masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED); 5286 masm, r1, r5, r2, r3, r4, r6, r9, DEST_ALWAYS_ALIGNED);
5294 5287
5295 __ bind(&return_r0); 5288 __ bind(&return_r0);
5296 Counters* counters = masm->isolate()->counters(); 5289 Counters* counters = masm->isolate()->counters();
5297 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); 5290 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
5298 __ Drop(3); 5291 __ Drop(3);
5299 __ Ret(); 5292 __ Ret();
5300 5293
5301 // Just jump to runtime to create the sub string. 5294 // Just jump to runtime to create the sub string.
5302 __ bind(&runtime); 5295 __ bind(&runtime);
5303 __ TailCallRuntime(Runtime::kSubString, 3, 1); 5296 __ TailCallRuntime(Runtime::kSubString, 3, 1);
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
5549 __ cmp(r6, Operand(2)); 5542 __ cmp(r6, Operand(2));
5550 __ b(ne, &longer_than_two); 5543 __ b(ne, &longer_than_two);
5551 5544
5552 // Check that both strings are non-external ASCII strings. 5545 // Check that both strings are non-external ASCII strings.
5553 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) { 5546 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
5554 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); 5547 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
5555 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); 5548 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
5556 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 5549 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
5557 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); 5550 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
5558 } 5551 }
5559 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, 5552 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r3,
5560 &call_runtime); 5553 &call_runtime);
5561 5554
5562 // Get the two characters forming the sub string. 5555 // Get the two characters forming the sub string.
5563 __ ldrb(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize)); 5556 __ ldrb(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize));
5564 __ ldrb(r3, FieldMemOperand(r1, SeqOneByteString::kHeaderSize)); 5557 __ ldrb(r3, FieldMemOperand(r1, SeqOneByteString::kHeaderSize));
5565 5558
5566 // Try to lookup two character string in string table. If it is not found 5559 // Try to lookup two character string in string table. If it is not found
5567 // just allocate a new one. 5560 // just allocate a new one.
5568 Label make_two_character_string; 5561 Label make_two_character_string;
5569 StringHelper::GenerateTwoCharacterStringTableProbe( 5562 StringHelper::GenerateTwoCharacterStringTableProbe(
5570 masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string); 5563 masm, r2, r3, r6, r0, r4, r5, r9, &make_two_character_string);
5571 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); 5564 __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
5572 __ add(sp, sp, Operand(2 * kPointerSize)); 5565 __ add(sp, sp, Operand(2 * kPointerSize));
5573 __ Ret(); 5566 __ Ret();
5574 5567
5575 __ bind(&make_two_character_string); 5568 __ bind(&make_two_character_string);
5576 // Resulting string has length 2 and first chars of two strings 5569 // Resulting string has length 2 and first chars of two strings
5577 // are combined into single halfword in r2 register. 5570 // are combined into single halfword in r2 register.
5578 // So we can fill resulting string without two loops by a single 5571 // So we can fill resulting string without two loops by a single
5579 // halfword store instruction (which assumes that processor is 5572 // halfword store instruction (which assumes that processor is
5580 // in a little endian mode) 5573 // in a little endian mode)
(...skipping 24 matching lines...) Expand all
5605 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); 5598 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
5606 } 5599 }
5607 Label non_ascii, allocated, ascii_data; 5600 Label non_ascii, allocated, ascii_data;
5608 STATIC_ASSERT(kTwoByteStringTag == 0); 5601 STATIC_ASSERT(kTwoByteStringTag == 0);
5609 __ tst(r4, Operand(kStringEncodingMask)); 5602 __ tst(r4, Operand(kStringEncodingMask));
5610 __ tst(r5, Operand(kStringEncodingMask), ne); 5603 __ tst(r5, Operand(kStringEncodingMask), ne);
5611 __ b(eq, &non_ascii); 5604 __ b(eq, &non_ascii);
5612 5605
5613 // Allocate an ASCII cons string. 5606 // Allocate an ASCII cons string.
5614 __ bind(&ascii_data); 5607 __ bind(&ascii_data);
5615 __ AllocateAsciiConsString(r7, r6, r4, r5, &call_runtime); 5608 __ AllocateAsciiConsString(r3, r6, r4, r5, &call_runtime);
5616 __ bind(&allocated); 5609 __ bind(&allocated);
5617 // Fill the fields of the cons string. 5610 // Fill the fields of the cons string.
5618 Label skip_write_barrier, after_writing; 5611 Label skip_write_barrier, after_writing;
5619 ExternalReference high_promotion_mode = ExternalReference:: 5612 ExternalReference high_promotion_mode = ExternalReference::
5620 new_space_high_promotion_mode_active_address(masm->isolate()); 5613 new_space_high_promotion_mode_active_address(masm->isolate());
5621 __ mov(r4, Operand(high_promotion_mode)); 5614 __ mov(r4, Operand(high_promotion_mode));
5622 __ ldr(r4, MemOperand(r4, 0)); 5615 __ ldr(r4, MemOperand(r4, 0));
5623 __ cmp(r4, Operand::Zero()); 5616 __ cmp(r4, Operand::Zero());
5624 __ b(eq, &skip_write_barrier); 5617 __ b(eq, &skip_write_barrier);
5625 5618
5626 __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset)); 5619 __ str(r0, FieldMemOperand(r3, ConsString::kFirstOffset));
5627 __ RecordWriteField(r7, 5620 __ RecordWriteField(r3,
5628 ConsString::kFirstOffset, 5621 ConsString::kFirstOffset,
5629 r0, 5622 r0,
5630 r4, 5623 r4,
5631 kLRHasNotBeenSaved, 5624 kLRHasNotBeenSaved,
5632 kDontSaveFPRegs); 5625 kDontSaveFPRegs);
5633 __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset)); 5626 __ str(r1, FieldMemOperand(r3, ConsString::kSecondOffset));
5634 __ RecordWriteField(r7, 5627 __ RecordWriteField(r3,
5635 ConsString::kSecondOffset, 5628 ConsString::kSecondOffset,
5636 r1, 5629 r1,
5637 r4, 5630 r4,
5638 kLRHasNotBeenSaved, 5631 kLRHasNotBeenSaved,
5639 kDontSaveFPRegs); 5632 kDontSaveFPRegs);
5640 __ jmp(&after_writing); 5633 __ jmp(&after_writing);
5641 5634
5642 __ bind(&skip_write_barrier); 5635 __ bind(&skip_write_barrier);
5643 __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset)); 5636 __ str(r0, FieldMemOperand(r3, ConsString::kFirstOffset));
5644 __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset)); 5637 __ str(r1, FieldMemOperand(r3, ConsString::kSecondOffset));
5645 5638
5646 __ bind(&after_writing); 5639 __ bind(&after_writing);
5647 5640
5648 __ mov(r0, Operand(r7)); 5641 __ mov(r0, Operand(r3));
5649 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); 5642 __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
5650 __ add(sp, sp, Operand(2 * kPointerSize)); 5643 __ add(sp, sp, Operand(2 * kPointerSize));
5651 __ Ret(); 5644 __ Ret();
5652 5645
5653 __ bind(&non_ascii); 5646 __ bind(&non_ascii);
5654 // At least one of the strings is two-byte. Check whether it happens 5647 // At least one of the strings is two-byte. Check whether it happens
5655 // to contain only one byte characters. 5648 // to contain only one byte characters.
5656 // r4: first instance type. 5649 // r4: first instance type.
5657 // r5: second instance type. 5650 // r5: second instance type.
5658 __ tst(r4, Operand(kOneByteDataHintMask)); 5651 __ tst(r4, Operand(kOneByteDataHintMask));
5659 __ tst(r5, Operand(kOneByteDataHintMask), ne); 5652 __ tst(r5, Operand(kOneByteDataHintMask), ne);
5660 __ b(ne, &ascii_data); 5653 __ b(ne, &ascii_data);
5661 __ eor(r4, r4, Operand(r5)); 5654 __ eor(r4, r4, Operand(r5));
5662 STATIC_ASSERT(kOneByteStringTag != 0 && kOneByteDataHintTag != 0); 5655 STATIC_ASSERT(kOneByteStringTag != 0 && kOneByteDataHintTag != 0);
5663 __ and_(r4, r4, Operand(kOneByteStringTag | kOneByteDataHintTag)); 5656 __ and_(r4, r4, Operand(kOneByteStringTag | kOneByteDataHintTag));
5664 __ cmp(r4, Operand(kOneByteStringTag | kOneByteDataHintTag)); 5657 __ cmp(r4, Operand(kOneByteStringTag | kOneByteDataHintTag));
5665 __ b(eq, &ascii_data); 5658 __ b(eq, &ascii_data);
5666 5659
5667 // Allocate a two byte cons string. 5660 // Allocate a two byte cons string.
5668 __ AllocateTwoByteConsString(r7, r6, r4, r5, &call_runtime); 5661 __ AllocateTwoByteConsString(r3, r6, r4, r5, &call_runtime);
5669 __ jmp(&allocated); 5662 __ jmp(&allocated);
5670 5663
5671 // We cannot encounter sliced strings or cons strings here since: 5664 // We cannot encounter sliced strings or cons strings here since:
5672 STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength); 5665 STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
5673 // Handle creating a flat result from either external or sequential strings. 5666 // Handle creating a flat result from either external or sequential strings.
5674 // Locate the first characters' locations. 5667 // Locate the first characters' locations.
5675 // r0: first string 5668 // r0: first string
5676 // r1: second string 5669 // r1: second string
5677 // r2: length of first string 5670 // r2: length of first string
5678 // r3: length of second string 5671 // r3: length of second string
5679 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) 5672 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
5680 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) 5673 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
5681 // r6: sum of lengths. 5674 // r6: sum of lengths.
5682 Label first_prepared, second_prepared; 5675 Label first_prepared, second_prepared;
5683 __ bind(&string_add_flat_result); 5676 __ bind(&string_add_flat_result);
5684 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) { 5677 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
5685 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); 5678 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
5686 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); 5679 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
5687 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 5680 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
5688 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); 5681 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
5689 } 5682 }
5690 5683
5691 // Check whether both strings have same encoding 5684 // Check whether both strings have same encoding
5692 __ eor(r7, r4, Operand(r5)); 5685 __ eor(ip, r4, Operand(r5));
5693 __ tst(r7, Operand(kStringEncodingMask)); 5686 __ tst(ip, Operand(kStringEncodingMask));
5694 __ b(ne, &call_runtime); 5687 __ b(ne, &call_runtime);
5695 5688
5696 STATIC_ASSERT(kSeqStringTag == 0); 5689 STATIC_ASSERT(kSeqStringTag == 0);
5697 __ tst(r4, Operand(kStringRepresentationMask)); 5690 __ tst(r4, Operand(kStringRepresentationMask));
5698 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); 5691 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
5699 __ add(r7, 5692 __ add(r6,
5700 r0, 5693 r0,
5701 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag), 5694 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag),
5702 LeaveCC, 5695 LeaveCC,
5703 eq); 5696 eq);
5704 __ b(eq, &first_prepared); 5697 __ b(eq, &first_prepared);
5705 // External string: rule out short external string and load string resource. 5698 // External string: rule out short external string and load string resource.
5706 STATIC_ASSERT(kShortExternalStringTag != 0); 5699 STATIC_ASSERT(kShortExternalStringTag != 0);
5707 __ tst(r4, Operand(kShortExternalStringMask)); 5700 __ tst(r4, Operand(kShortExternalStringMask));
5708 __ b(ne, &call_runtime); 5701 __ b(ne, &call_runtime);
5709 __ ldr(r7, FieldMemOperand(r0, ExternalString::kResourceDataOffset)); 5702 __ ldr(r6, FieldMemOperand(r0, ExternalString::kResourceDataOffset));
5710 __ bind(&first_prepared); 5703 __ bind(&first_prepared);
5711 5704
5712 STATIC_ASSERT(kSeqStringTag == 0); 5705 STATIC_ASSERT(kSeqStringTag == 0);
5713 __ tst(r5, Operand(kStringRepresentationMask)); 5706 __ tst(r5, Operand(kStringRepresentationMask));
5714 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); 5707 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
5715 __ add(r1, 5708 __ add(r1,
5716 r1, 5709 r1,
5717 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag), 5710 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag),
5718 LeaveCC, 5711 LeaveCC,
5719 eq); 5712 eq);
5720 __ b(eq, &second_prepared); 5713 __ b(eq, &second_prepared);
5721 // External string: rule out short external string and load string resource. 5714 // External string: rule out short external string and load string resource.
5722 STATIC_ASSERT(kShortExternalStringTag != 0); 5715 STATIC_ASSERT(kShortExternalStringTag != 0);
5723 __ tst(r5, Operand(kShortExternalStringMask)); 5716 __ tst(r5, Operand(kShortExternalStringMask));
5724 __ b(ne, &call_runtime); 5717 __ b(ne, &call_runtime);
5725 __ ldr(r1, FieldMemOperand(r1, ExternalString::kResourceDataOffset)); 5718 __ ldr(r1, FieldMemOperand(r1, ExternalString::kResourceDataOffset));
5726 __ bind(&second_prepared); 5719 __ bind(&second_prepared);
5727 5720
5728 Label non_ascii_string_add_flat_result; 5721 Label non_ascii_string_add_flat_result;
5729 // r7: first character of first string 5722 // r6: first character of first string
5730 // r1: first character of second string 5723 // r1: first character of second string
5731 // r2: length of first string. 5724 // r2: length of first string.
5732 // r3: length of second string. 5725 // r3: length of second string.
5733 // r6: sum of lengths.
5734 // Both strings have the same encoding. 5726 // Both strings have the same encoding.
5735 STATIC_ASSERT(kTwoByteStringTag == 0); 5727 STATIC_ASSERT(kTwoByteStringTag == 0);
5736 __ tst(r5, Operand(kStringEncodingMask)); 5728 __ tst(r5, Operand(kStringEncodingMask));
5737 __ b(eq, &non_ascii_string_add_flat_result); 5729 __ b(eq, &non_ascii_string_add_flat_result);
5738 5730
5739 __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime); 5731 __ add(r2, r2, Operand(r3));
5740 __ add(r6, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 5732 __ AllocateAsciiString(r0, r2, r4, r5, r9, &call_runtime);
5733 __ sub(r2, r2, Operand(r3));
5734 __ add(r5, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
5741 // r0: result string. 5735 // r0: result string.
5742 // r7: first character of first string. 5736 // r6: first character of first string.
5743 // r1: first character of second string. 5737 // r1: first character of second string.
5744 // r2: length of first string. 5738 // r2: length of first string.
5745 // r3: length of second string. 5739 // r3: length of second string.
5746 // r6: first character of result. 5740 // r5: first character of result.
5747 StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, true); 5741 StringHelper::GenerateCopyCharacters(masm, r5, r6, r2, r4, true);
5748 // r6: next character of result. 5742 // r5: next character of result.
5749 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true); 5743 StringHelper::GenerateCopyCharacters(masm, r5, r1, r3, r4, true);
5750 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); 5744 __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
5751 __ add(sp, sp, Operand(2 * kPointerSize)); 5745 __ add(sp, sp, Operand(2 * kPointerSize));
5752 __ Ret(); 5746 __ Ret();
5753 5747
5754 __ bind(&non_ascii_string_add_flat_result); 5748 __ bind(&non_ascii_string_add_flat_result);
5755 __ AllocateTwoByteString(r0, r6, r4, r5, r9, &call_runtime); 5749 __ add(r2, r2, Operand(r3));
5756 __ add(r6, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 5750 __ AllocateTwoByteString(r0, r2, r4, r5, r9, &call_runtime);
5751 __ sub(r2, r2, Operand(r3));
5752 __ add(r5, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
5757 // r0: result string. 5753 // r0: result string.
5758 // r7: first character of first string. 5754 // r6: first character of first string.
5759 // r1: first character of second string. 5755 // r1: first character of second string.
5760 // r2: length of first string. 5756 // r2: length of first string.
5761 // r3: length of second string. 5757 // r3: length of second string.
5762 // r6: first character of result. 5758 // r5: first character of result.
5763 StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, false); 5759 StringHelper::GenerateCopyCharacters(masm, r5, r6, r2, r4, false);
5764 // r6: next character of result. 5760 // r5: next character of result.
5765 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false); 5761 StringHelper::GenerateCopyCharacters(masm, r5, r1, r3, r4, false);
5766 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); 5762 __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
5767 __ add(sp, sp, Operand(2 * kPointerSize)); 5763 __ add(sp, sp, Operand(2 * kPointerSize));
5768 __ Ret(); 5764 __ Ret();
5769 5765
5770 // Just jump to runtime to add the two strings. 5766 // Just jump to runtime to add the two strings.
5771 __ bind(&call_runtime); 5767 __ bind(&call_runtime);
5772 if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) { 5768 if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) {
5773 GenerateRegisterArgsPop(masm); 5769 GenerateRegisterArgsPop(masm);
5774 // Build a frame 5770 // Build a frame
5775 { 5771 {
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
6456 struct AheadOfTimeWriteBarrierStubList { 6452 struct AheadOfTimeWriteBarrierStubList {
6457 Register object, value, address; 6453 Register object, value, address;
6458 RememberedSetAction action; 6454 RememberedSetAction action;
6459 }; 6455 };
6460 6456
6461 6457
6462 #define REG(Name) { kRegister_ ## Name ## _Code } 6458 #define REG(Name) { kRegister_ ## Name ## _Code }
6463 6459
6464 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { 6460 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
6465 // Used in RegExpExecStub. 6461 // Used in RegExpExecStub.
6466 { REG(r6), REG(r4), REG(r7), EMIT_REMEMBERED_SET }, 6462 { REG(r6), REG(r4), REG(r3), EMIT_REMEMBERED_SET },
6467 // Used in CompileArrayPushCall. 6463 // Used in CompileArrayPushCall.
6468 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. 6464 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore.
6469 // Also used in KeyedStoreIC::GenerateGeneric. 6465 // Also used in KeyedStoreIC::GenerateGeneric.
6470 { REG(r3), REG(r4), REG(r5), EMIT_REMEMBERED_SET }, 6466 { REG(r3), REG(r4), REG(r5), EMIT_REMEMBERED_SET },
6471 // Used in CompileStoreGlobal. 6467 // Used in CompileStoreGlobal.
6472 { REG(r4), REG(r1), REG(r2), OMIT_REMEMBERED_SET }, 6468 { REG(r4), REG(r1), REG(r2), OMIT_REMEMBERED_SET },
6473 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. 6469 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField.
6474 { REG(r1), REG(r2), REG(r3), EMIT_REMEMBERED_SET }, 6470 { REG(r1), REG(r2), REG(r3), EMIT_REMEMBERED_SET },
6475 { REG(r3), REG(r2), REG(r1), EMIT_REMEMBERED_SET }, 6471 { REG(r3), REG(r2), REG(r1), EMIT_REMEMBERED_SET },
6476 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. 6472 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField.
6477 { REG(r2), REG(r1), REG(r3), EMIT_REMEMBERED_SET }, 6473 { REG(r2), REG(r1), REG(r3), EMIT_REMEMBERED_SET },
6478 { REG(r3), REG(r1), REG(r2), EMIT_REMEMBERED_SET }, 6474 { REG(r3), REG(r1), REG(r2), EMIT_REMEMBERED_SET },
6479 // KeyedStoreStubCompiler::GenerateStoreFastElement. 6475 // KeyedStoreStubCompiler::GenerateStoreFastElement.
6480 { REG(r3), REG(r2), REG(r4), EMIT_REMEMBERED_SET }, 6476 { REG(r3), REG(r2), REG(r4), EMIT_REMEMBERED_SET },
6481 { REG(r2), REG(r3), REG(r4), EMIT_REMEMBERED_SET }, 6477 { REG(r2), REG(r3), REG(r4), EMIT_REMEMBERED_SET },
6482 // ElementsTransitionGenerator::GenerateMapChangeElementTransition 6478 // ElementsTransitionGenerator::GenerateMapChangeElementTransition
6483 // and ElementsTransitionGenerator::GenerateSmiToDouble 6479 // and ElementsTransitionGenerator::GenerateSmiToDouble
6484 // and ElementsTransitionGenerator::GenerateDoubleToObject 6480 // and ElementsTransitionGenerator::GenerateDoubleToObject
6485 { REG(r2), REG(r3), REG(r9), EMIT_REMEMBERED_SET }, 6481 { REG(r2), REG(r3), REG(r9), EMIT_REMEMBERED_SET },
6486 { REG(r2), REG(r3), REG(r9), OMIT_REMEMBERED_SET }, 6482 { REG(r2), REG(r3), REG(r9), OMIT_REMEMBERED_SET },
6487 // ElementsTransitionGenerator::GenerateDoubleToObject 6483 // ElementsTransitionGenerator::GenerateDoubleToObject
6488 { REG(r6), REG(r2), REG(r0), EMIT_REMEMBERED_SET }, 6484 { REG(r6), REG(r2), REG(r0), EMIT_REMEMBERED_SET },
6489 { REG(r2), REG(r6), REG(r9), EMIT_REMEMBERED_SET }, 6485 { REG(r2), REG(r6), REG(r9), EMIT_REMEMBERED_SET },
6490 // StoreArrayLiteralElementStub::Generate 6486 // StoreArrayLiteralElementStub::Generate
6491 { REG(r5), REG(r0), REG(r6), EMIT_REMEMBERED_SET }, 6487 { REG(r5), REG(r0), REG(r6), EMIT_REMEMBERED_SET },
6492 // FastNewClosureStub::Generate 6488 // FastNewClosureStub::Generate
6493 { REG(r2), REG(r4), REG(r1), EMIT_REMEMBERED_SET }, 6489 { REG(r2), REG(r4), REG(r1), EMIT_REMEMBERED_SET },
6494 // StringAddStub::Generate 6490 // StringAddStub::Generate
6495 { REG(r7), REG(r1), REG(r4), EMIT_REMEMBERED_SET }, 6491 { REG(r3), REG(r1), REG(r4), EMIT_REMEMBERED_SET },
6496 { REG(r7), REG(r0), REG(r4), EMIT_REMEMBERED_SET }, 6492 { REG(r3), REG(r0), REG(r4), EMIT_REMEMBERED_SET },
6497 // Null termination. 6493 // Null termination.
6498 { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET} 6494 { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET}
6499 }; 6495 };
6500 6496
6501 #undef REG 6497 #undef REG
6502 6498
6503 6499
6504 bool RecordWriteStub::IsPregenerated() { 6500 bool RecordWriteStub::IsPregenerated() {
6505 for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; 6501 for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
6506 !entry->object.is(no_reg); 6502 !entry->object.is(no_reg);
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after
7175 __ bind(&fast_elements_case); 7171 __ bind(&fast_elements_case);
7176 GenerateCase(masm, FAST_ELEMENTS); 7172 GenerateCase(masm, FAST_ELEMENTS);
7177 } 7173 }
7178 7174
7179 7175
7180 #undef __ 7176 #undef __
7181 7177
7182 } } // namespace v8::internal 7178 } } // namespace v8::internal
7183 7179
7184 #endif // V8_TARGET_ARCH_ARM 7180 #endif // V8_TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698