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 2943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2954 __ bind(&call_runtime); | 2954 __ bind(&call_runtime); |
2955 GenerateCallRuntime(masm); | 2955 GenerateCallRuntime(masm); |
2956 } | 2956 } |
2957 | 2957 |
2958 | 2958 |
2959 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { | 2959 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { |
2960 ASSERT(op_ == Token::ADD); | 2960 ASSERT(op_ == Token::ADD); |
2961 | 2961 |
2962 Register left = r1; | 2962 Register left = r1; |
2963 Register right = r0; | 2963 Register right = r0; |
2964 Label call_runtime; | 2964 Label left_not_string, call_runtime; |
2965 | 2965 |
2966 // Check if first argument is a string. | 2966 // Check if left argument is a string. |
2967 __ JumpIfSmi(left, &call_runtime); | 2967 __ JumpIfSmi(left, &left_not_string); |
2968 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); | 2968 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); |
2969 __ b(ge, &call_runtime); | 2969 __ b(ge, &left_not_string); |
2970 | 2970 |
2971 // First argument is a a string, test second. | 2971 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); |
| 2972 GenerateRegisterArgsPush(masm); |
| 2973 __ TailCallStub(&string_add_left_stub); |
| 2974 |
| 2975 // Left operand is not a string, test right. |
| 2976 __ bind(&left_not_string); |
2972 __ JumpIfSmi(right, &call_runtime); | 2977 __ JumpIfSmi(right, &call_runtime); |
2973 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE); | 2978 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE); |
2974 __ b(ge, &call_runtime); | 2979 __ b(ge, &call_runtime); |
2975 | 2980 |
2976 // First and second argument are strings. | 2981 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); |
2977 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); | |
2978 GenerateRegisterArgsPush(masm); | 2982 GenerateRegisterArgsPush(masm); |
2979 __ TailCallStub(&string_add_stub); | 2983 __ TailCallStub(&string_add_right_stub); |
2980 | 2984 |
2981 // At least one argument is not a string. | 2985 // At least one argument is not a string. |
2982 __ bind(&call_runtime); | 2986 __ bind(&call_runtime); |
2983 } | 2987 } |
2984 | 2988 |
2985 | 2989 |
2986 void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) { | 2990 void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) { |
2987 GenerateRegisterArgsPush(masm); | 2991 GenerateRegisterArgsPush(masm); |
2988 switch (op_) { | 2992 switch (op_) { |
2989 case Token::ADD: | 2993 case Token::ADD: |
(...skipping 2445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5435 GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5); | 5439 GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5); |
5436 | 5440 |
5437 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 5441 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
5438 // tagged as a small integer. | 5442 // tagged as a small integer. |
5439 __ bind(&runtime); | 5443 __ bind(&runtime); |
5440 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 5444 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
5441 } | 5445 } |
5442 | 5446 |
5443 | 5447 |
5444 void StringAddStub::Generate(MacroAssembler* masm) { | 5448 void StringAddStub::Generate(MacroAssembler* masm) { |
5445 Label string_add_runtime; | 5449 Label string_add_runtime, call_builtin; |
| 5450 Builtins::JavaScript builtin_id = Builtins::ADD; |
| 5451 |
5446 // Stack on entry: | 5452 // Stack on entry: |
5447 // sp[0]: second argument. | 5453 // sp[0]: second argument (right). |
5448 // sp[4]: first argument. | 5454 // sp[4]: first argument (left). |
5449 | 5455 |
5450 // Load the two arguments. | 5456 // Load the two arguments. |
5451 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // First argument. | 5457 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // First argument. |
5452 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // Second argument. | 5458 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // Second argument. |
5453 | 5459 |
5454 // Make sure that both arguments are strings if not known in advance. | 5460 // Make sure that both arguments are strings if not known in advance. |
5455 if (string_check_) { | 5461 if (flags_ == NO_STRING_ADD_FLAGS) { |
5456 STATIC_ASSERT(kSmiTag == 0); | |
5457 __ JumpIfEitherSmi(r0, r1, &string_add_runtime); | 5462 __ JumpIfEitherSmi(r0, r1, &string_add_runtime); |
5458 // Load instance types. | 5463 // Load instance types. |
5459 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5464 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
5460 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 5465 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
5461 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 5466 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
5462 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 5467 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
5463 STATIC_ASSERT(kStringTag == 0); | 5468 STATIC_ASSERT(kStringTag == 0); |
5464 // If either is not a string, go to runtime. | 5469 // If either is not a string, go to runtime. |
5465 __ tst(r4, Operand(kIsNotStringMask)); | 5470 __ tst(r4, Operand(kIsNotStringMask)); |
5466 __ tst(r5, Operand(kIsNotStringMask), eq); | 5471 __ tst(r5, Operand(kIsNotStringMask), eq); |
5467 __ b(ne, &string_add_runtime); | 5472 __ b(ne, &string_add_runtime); |
| 5473 } else { |
| 5474 // Here at least one of the arguments is definitely a string. |
| 5475 // We convert the one that is not known to be a string. |
| 5476 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { |
| 5477 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); |
| 5478 GenerateConvertArgument( |
| 5479 masm, 1 * kPointerSize, r0, r2, r3, r4, r5, &call_builtin); |
| 5480 builtin_id = Builtins::STRING_ADD_RIGHT; |
| 5481 } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) { |
| 5482 ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0); |
| 5483 GenerateConvertArgument( |
| 5484 masm, 0 * kPointerSize, r1, r2, r3, r4, r5, &call_builtin); |
| 5485 builtin_id = Builtins::STRING_ADD_LEFT; |
| 5486 } |
5468 } | 5487 } |
5469 | 5488 |
5470 // Both arguments are strings. | 5489 // Both arguments are strings. |
5471 // r0: first string | 5490 // r0: first string |
5472 // r1: second string | 5491 // r1: second string |
5473 // r4: first string instance type (if string_check_) | 5492 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
5474 // r5: second string instance type (if string_check_) | 5493 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
5475 { | 5494 { |
5476 Label strings_not_empty; | 5495 Label strings_not_empty; |
5477 // Check if either of the strings are empty. In that case return the other. | 5496 // Check if either of the strings are empty. In that case return the other. |
5478 __ ldr(r2, FieldMemOperand(r0, String::kLengthOffset)); | 5497 __ ldr(r2, FieldMemOperand(r0, String::kLengthOffset)); |
5479 __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset)); | 5498 __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset)); |
5480 STATIC_ASSERT(kSmiTag == 0); | 5499 STATIC_ASSERT(kSmiTag == 0); |
5481 __ cmp(r2, Operand(Smi::FromInt(0))); // Test if first string is empty. | 5500 __ cmp(r2, Operand(Smi::FromInt(0))); // Test if first string is empty. |
5482 __ mov(r0, Operand(r1), LeaveCC, eq); // If first is empty, return second. | 5501 __ mov(r0, Operand(r1), LeaveCC, eq); // If first is empty, return second. |
5483 STATIC_ASSERT(kSmiTag == 0); | 5502 STATIC_ASSERT(kSmiTag == 0); |
5484 // Else test if second string is empty. | 5503 // Else test if second string is empty. |
5485 __ cmp(r3, Operand(Smi::FromInt(0)), ne); | 5504 __ cmp(r3, Operand(Smi::FromInt(0)), ne); |
5486 __ b(ne, &strings_not_empty); // If either string was empty, return r0. | 5505 __ b(ne, &strings_not_empty); // If either string was empty, return r0. |
5487 | 5506 |
5488 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3); | 5507 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3); |
5489 __ add(sp, sp, Operand(2 * kPointerSize)); | 5508 __ add(sp, sp, Operand(2 * kPointerSize)); |
5490 __ Ret(); | 5509 __ Ret(); |
5491 | 5510 |
5492 __ bind(&strings_not_empty); | 5511 __ bind(&strings_not_empty); |
5493 } | 5512 } |
5494 | 5513 |
5495 __ mov(r2, Operand(r2, ASR, kSmiTagSize)); | 5514 __ mov(r2, Operand(r2, ASR, kSmiTagSize)); |
5496 __ mov(r3, Operand(r3, ASR, kSmiTagSize)); | 5515 __ mov(r3, Operand(r3, ASR, kSmiTagSize)); |
5497 // Both strings are non-empty. | 5516 // Both strings are non-empty. |
5498 // r0: first string | 5517 // r0: first string |
5499 // r1: second string | 5518 // r1: second string |
5500 // r2: length of first string | 5519 // r2: length of first string |
5501 // r3: length of second string | 5520 // r3: length of second string |
5502 // r4: first string instance type (if string_check_) | 5521 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
5503 // r5: second string instance type (if string_check_) | 5522 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
5504 // Look at the length of the result of adding the two strings. | 5523 // Look at the length of the result of adding the two strings. |
5505 Label string_add_flat_result, longer_than_two; | 5524 Label string_add_flat_result, longer_than_two; |
5506 // Adding two lengths can't overflow. | 5525 // Adding two lengths can't overflow. |
5507 STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2); | 5526 STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2); |
5508 __ add(r6, r2, Operand(r3)); | 5527 __ add(r6, r2, Operand(r3)); |
5509 // Use the runtime system when adding two one character strings, as it | 5528 // Use the runtime system when adding two one character strings, as it |
5510 // contains optimizations for this specific case using the symbol table. | 5529 // contains optimizations for this specific case using the symbol table. |
5511 __ cmp(r6, Operand(2)); | 5530 __ cmp(r6, Operand(2)); |
5512 __ b(ne, &longer_than_two); | 5531 __ b(ne, &longer_than_two); |
5513 | 5532 |
5514 // Check that both strings are non-external ascii strings. | 5533 // Check that both strings are non-external ascii strings. |
5515 if (!string_check_) { | 5534 if (flags_ != NO_STRING_ADD_FLAGS) { |
5516 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5535 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
5517 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 5536 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
5518 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 5537 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
5519 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 5538 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
5520 } | 5539 } |
5521 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, | 5540 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, |
5522 &string_add_runtime); | 5541 &string_add_runtime); |
5523 | 5542 |
5524 // Get the two characters forming the sub string. | 5543 // Get the two characters forming the sub string. |
5525 __ ldrb(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); | 5544 __ ldrb(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); |
(...skipping 27 matching lines...) Expand all Loading... |
5553 __ b(lt, &string_add_flat_result); | 5572 __ b(lt, &string_add_flat_result); |
5554 // Handle exceptionally long strings in the runtime system. | 5573 // Handle exceptionally long strings in the runtime system. |
5555 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); | 5574 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); |
5556 ASSERT(IsPowerOf2(String::kMaxLength + 1)); | 5575 ASSERT(IsPowerOf2(String::kMaxLength + 1)); |
5557 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. | 5576 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. |
5558 __ cmp(r6, Operand(String::kMaxLength + 1)); | 5577 __ cmp(r6, Operand(String::kMaxLength + 1)); |
5559 __ b(hs, &string_add_runtime); | 5578 __ b(hs, &string_add_runtime); |
5560 | 5579 |
5561 // If result is not supposed to be flat, allocate a cons string object. | 5580 // If result is not supposed to be flat, allocate a cons string object. |
5562 // If both strings are ascii the result is an ascii cons string. | 5581 // If both strings are ascii the result is an ascii cons string. |
5563 if (!string_check_) { | 5582 if (flags_ != NO_STRING_ADD_FLAGS) { |
5564 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5583 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
5565 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 5584 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
5566 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 5585 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
5567 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 5586 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
5568 } | 5587 } |
5569 Label non_ascii, allocated, ascii_data; | 5588 Label non_ascii, allocated, ascii_data; |
5570 STATIC_ASSERT(kTwoByteStringTag == 0); | 5589 STATIC_ASSERT(kTwoByteStringTag == 0); |
5571 __ tst(r4, Operand(kStringEncodingMask)); | 5590 __ tst(r4, Operand(kStringEncodingMask)); |
5572 __ tst(r5, Operand(kStringEncodingMask), ne); | 5591 __ tst(r5, Operand(kStringEncodingMask), ne); |
5573 __ b(eq, &non_ascii); | 5592 __ b(eq, &non_ascii); |
(...skipping 27 matching lines...) Expand all Loading... |
5601 // Allocate a two byte cons string. | 5620 // Allocate a two byte cons string. |
5602 __ AllocateTwoByteConsString(r7, r6, r4, r5, &string_add_runtime); | 5621 __ AllocateTwoByteConsString(r7, r6, r4, r5, &string_add_runtime); |
5603 __ jmp(&allocated); | 5622 __ jmp(&allocated); |
5604 | 5623 |
5605 // Handle creating a flat result. First check that both strings are | 5624 // Handle creating a flat result. First check that both strings are |
5606 // sequential and that they have the same encoding. | 5625 // sequential and that they have the same encoding. |
5607 // r0: first string | 5626 // r0: first string |
5608 // r1: second string | 5627 // r1: second string |
5609 // r2: length of first string | 5628 // r2: length of first string |
5610 // r3: length of second string | 5629 // r3: length of second string |
5611 // r4: first string instance type (if string_check_) | 5630 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
5612 // r5: second string instance type (if string_check_) | 5631 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
5613 // r6: sum of lengths. | 5632 // r6: sum of lengths. |
5614 __ bind(&string_add_flat_result); | 5633 __ bind(&string_add_flat_result); |
5615 if (!string_check_) { | 5634 if (flags_ != NO_STRING_ADD_FLAGS) { |
5616 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5635 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
5617 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 5636 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
5618 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 5637 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
5619 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 5638 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
5620 } | 5639 } |
5621 // Check that both strings are sequential. | 5640 // Check that both strings are sequential. |
5622 STATIC_ASSERT(kSeqStringTag == 0); | 5641 STATIC_ASSERT(kSeqStringTag == 0); |
5623 __ tst(r4, Operand(kStringRepresentationMask)); | 5642 __ tst(r4, Operand(kStringRepresentationMask)); |
5624 __ tst(r5, Operand(kStringRepresentationMask), eq); | 5643 __ tst(r5, Operand(kStringRepresentationMask), eq); |
5625 __ b(ne, &string_add_runtime); | 5644 __ b(ne, &string_add_runtime); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5703 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false); | 5722 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false); |
5704 | 5723 |
5705 __ mov(r0, Operand(r7)); | 5724 __ mov(r0, Operand(r7)); |
5706 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3); | 5725 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3); |
5707 __ add(sp, sp, Operand(2 * kPointerSize)); | 5726 __ add(sp, sp, Operand(2 * kPointerSize)); |
5708 __ Ret(); | 5727 __ Ret(); |
5709 | 5728 |
5710 // Just jump to runtime to add the two strings. | 5729 // Just jump to runtime to add the two strings. |
5711 __ bind(&string_add_runtime); | 5730 __ bind(&string_add_runtime); |
5712 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 5731 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
| 5732 |
| 5733 if (call_builtin.is_linked()) { |
| 5734 __ bind(&call_builtin); |
| 5735 __ InvokeBuiltin(builtin_id, JUMP_JS); |
| 5736 } |
| 5737 } |
| 5738 |
| 5739 |
| 5740 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm, |
| 5741 int stack_offset, |
| 5742 Register arg, |
| 5743 Register scratch1, |
| 5744 Register scratch2, |
| 5745 Register scratch3, |
| 5746 Register scratch4, |
| 5747 Label* slow) { |
| 5748 // First check if the argument is already a string. |
| 5749 Label not_string, done; |
| 5750 __ JumpIfSmi(arg, ¬_string); |
| 5751 __ CompareObjectType(arg, scratch1, scratch1, FIRST_NONSTRING_TYPE); |
| 5752 __ b(lt, &done); |
| 5753 |
| 5754 // Check the number to string cache. |
| 5755 Label not_cached; |
| 5756 __ bind(¬_string); |
| 5757 // Puts the cached result into scratch1. |
| 5758 NumberToStringStub::GenerateLookupNumberStringCache(masm, |
| 5759 arg, |
| 5760 scratch1, |
| 5761 scratch2, |
| 5762 scratch3, |
| 5763 scratch4, |
| 5764 false, |
| 5765 ¬_cached); |
| 5766 __ mov(arg, scratch1); |
| 5767 __ str(arg, MemOperand(sp, stack_offset)); |
| 5768 __ jmp(&done); |
| 5769 |
| 5770 // Check if the argument is a safe string wrapper. |
| 5771 __ bind(¬_cached); |
| 5772 __ JumpIfSmi(arg, slow); |
| 5773 __ CompareObjectType( |
| 5774 arg, scratch1, scratch2, JS_VALUE_TYPE); // map -> scratch1. |
| 5775 __ b(ne, slow); |
| 5776 __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitField2Offset)); |
| 5777 __ and_(scratch2, |
| 5778 scratch2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
| 5779 __ cmp(scratch2, |
| 5780 Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
| 5781 __ b(ne, slow); |
| 5782 __ ldr(arg, FieldMemOperand(arg, JSValue::kValueOffset)); |
| 5783 __ str(arg, MemOperand(sp, stack_offset)); |
| 5784 |
| 5785 __ bind(&done); |
5713 } | 5786 } |
5714 | 5787 |
5715 | 5788 |
5716 void StringCharAtStub::Generate(MacroAssembler* masm) { | 5789 void StringCharAtStub::Generate(MacroAssembler* masm) { |
5717 // Expects two arguments (object, index) on the stack: | 5790 // Expects two arguments (object, index) on the stack: |
5718 // lr: return address | 5791 // lr: return address |
5719 // sp[0]: index | 5792 // sp[0]: index |
5720 // sp[4]: object | 5793 // sp[4]: object |
5721 Register object = r1; | 5794 Register object = r1; |
5722 Register index = r0; | 5795 Register index = r0; |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6055 __ strb(untagged_value, MemOperand(external_pointer, untagged_key)); | 6128 __ strb(untagged_value, MemOperand(external_pointer, untagged_key)); |
6056 __ Ret(); | 6129 __ Ret(); |
6057 } | 6130 } |
6058 | 6131 |
6059 | 6132 |
6060 #undef __ | 6133 #undef __ |
6061 | 6134 |
6062 } } // namespace v8::internal | 6135 } } // namespace v8::internal |
6063 | 6136 |
6064 #endif // V8_TARGET_ARCH_ARM | 6137 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |