From 16d3811d500c5938ebdae4325a0f951818453ccf Mon Sep 17 00:00:00 2001 From: "serya@chromium.org" Date: Tue, 4 May 2010 14:49:50 +0000 Subject: [PATCH] Changing string length field type from int to SMI. It will make it be a regular field. Code generated in EmitNamedLoad could be patched for faster access to string.length. Review URL: http://codereview.chromium.org/1706013 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4581 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8.h | 2 +- src/arm/codegen-arm.cc | 28 +++++++--- src/arm/macro-assembler-arm.cc | 57 ++++++++++++-------- src/arm/macro-assembler-arm.h | 6 +++ src/arm/stub-cache-arm.cc | 2 - src/ia32/codegen-ia32.cc | 68 ++++++++++++++--------- src/ia32/macro-assembler-ia32.cc | 8 ++- src/ia32/stub-cache-ia32.cc | 2 - src/objects-inl.h | 8 ++- src/objects.h | 2 +- src/x64/codegen-x64.cc | 92 ++++++++++++++++++-------------- src/x64/macro-assembler-x64.cc | 69 +++++++++++++++++++++--- src/x64/macro-assembler-x64.h | 9 +++- src/x64/stub-cache-x64.cc | 6 +-- test/cctest/test-serialize.cc | 3 +- 15 files changed, 242 insertions(+), 120 deletions(-) diff --git a/include/v8.h b/include/v8.h index e777fa6b8b..c07ba1f0cf 100644 --- a/include/v8.h +++ b/include/v8.h @@ -3014,7 +3014,7 @@ template <> struct InternalConstants<4> { // Internal constants for 64-bit systems. template <> struct InternalConstants<8> { - static const int kStringResourceOffset = 2 * sizeof(void*); + static const int kStringResourceOffset = 3 * sizeof(void*); }; /** diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 33c9eb8210..f2bbac926a 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -8498,14 +8498,16 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ ldr(r3, FieldMemOperand(subject, String::kLengthOffset)); // r2: Number of capture registers - // r3: Length of subject string + // r3: Length of subject string as a smi // subject: Subject string // regexp_data: RegExp data (FixedArray) // Check that the third argument is a positive smi less than the subject // string length. A negative value will be greater (unsigned comparison). __ ldr(r0, MemOperand(sp, kPreviousIndexOffset)); - __ cmp(r3, Operand(r0, ASR, kSmiTagSize + kSmiShiftSize)); - __ b(ls, &runtime); + __ tst(r0, Operand(kSmiTagMask)); + __ b(eq, &runtime); + __ cmp(r3, Operand(r0)); + __ b(le, &runtime); // r2: Number of capture registers // subject: Subject string @@ -8631,6 +8633,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { // For arguments 4 and 3 get string length, calculate start of string data and // calculate the shift of the index (0 for ASCII and 1 for two byte). __ ldr(r0, FieldMemOperand(subject, String::kLengthOffset)); + __ mov(r0, Operand(r0, ASR, kSmiTagSize)); ASSERT_EQ(SeqAsciiString::kHeaderSize, SeqTwoByteString::kHeaderSize); __ add(r9, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); __ eor(r3, r3, Operand(1)); @@ -8890,7 +8893,7 @@ void StringHelper::GenerateFastCharCodeAt(MacroAssembler* masm, // Check for index out of range. __ ldr(scratch, FieldMemOperand(object, String::kLengthOffset)); // Now scratch has the length of the string. Compare with the index. - __ cmp(scratch, Operand(index, LSR, kSmiTagSize)); + __ cmp(scratch, Operand(index)); __ b(ls, index_out_of_range); __ bind(&try_again_with_new_string); @@ -9277,7 +9280,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, // If length is not 2 the string is not a candidate. __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); - __ cmp(scratch, Operand(2)); + __ cmp(scratch, Operand(Smi::FromInt(2))); __ b(ne, &next_probe[i]); // Check that the candidate is a non-external ascii string. @@ -9428,7 +9431,7 @@ void SubStringStub::Generate(MacroAssembler* masm) { // r6: from (smi) // r7: to (smi) __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset)); - __ cmp(r4, Operand(r7, ASR, 1)); + __ cmp(r4, Operand(r7)); __ b(lt, &runtime); // Fail if to > length. // r1: instance type. @@ -9547,9 +9550,13 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, Register length_delta = scratch3; __ mov(scratch1, scratch2, LeaveCC, gt); Register min_length = scratch1; + ASSERT(kSmiTag == 0); __ tst(min_length, Operand(min_length)); __ b(eq, &compare_lengths); + // Untag smi. + __ mov(min_length, Operand(min_length, ASR, kSmiTagSize)); + // Setup registers so that we only need to increment one register // in the loop. __ add(scratch2, min_length, @@ -9659,9 +9666,12 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Check if either of the strings are empty. In that case return the other. __ ldr(r2, FieldMemOperand(r0, String::kLengthOffset)); __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset)); - __ cmp(r2, Operand(0)); // Test if first string is empty. + ASSERT(kSmiTag == 0); + __ cmp(r2, Operand(Smi::FromInt(0))); // Test if first string is empty. __ mov(r0, Operand(r1), LeaveCC, eq); // If first is empty, return second. - __ cmp(r3, Operand(0), ne); // Else test if second string is empty. + ASSERT(kSmiTag == 0); + // Else test if second string is empty. + __ cmp(r3, Operand(Smi::FromInt(0)), ne); __ b(ne, &strings_not_empty); // If either string was empty, return r0. __ IncrementCounter(&Counters::string_add_native, 1, r2, r3); @@ -9671,6 +9681,8 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ bind(&strings_not_empty); } + __ mov(r2, Operand(r2, ASR, kSmiTagSize)); + __ mov(r3, Operand(r3, ASR, kSmiTagSize)); // Both strings are non-empty. // r0: first string // r1: second string diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index 935e7918b5..d97f04b71c 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -424,6 +424,20 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) { } +void MacroAssembler::InitializeNewString(Register string, + Register length, + Heap::RootListIndex map_index, + Register scratch1, + Register scratch2) { + mov(scratch1, Operand(length, LSL, kSmiTagSize)); + LoadRoot(scratch2, map_index); + str(scratch1, FieldMemOperand(string, String::kLengthOffset)); + mov(scratch1, Operand(String::kEmptyHashField)); + str(scratch2, FieldMemOperand(string, HeapObject::kMapOffset)); + str(scratch1, FieldMemOperand(string, String::kHashFieldOffset)); +} + + int MacroAssembler::ActivationFrameAlignment() { #if defined(V8_HOST_ARCH_ARM) // Running on the real platform. Use the alignment as mandated by the local @@ -1054,11 +1068,11 @@ void MacroAssembler::AllocateTwoByteString(Register result, TAG_OBJECT); // Set the map, length and hash field. - LoadRoot(scratch1, Heap::kStringMapRootIndex); - str(length, FieldMemOperand(result, String::kLengthOffset)); - str(scratch1, FieldMemOperand(result, HeapObject::kMapOffset)); - mov(scratch2, Operand(String::kEmptyHashField)); - str(scratch2, FieldMemOperand(result, String::kHashFieldOffset)); + InitializeNewString(result, + length, + Heap::kStringMapRootIndex, + scratch1, + scratch2); } @@ -1088,12 +1102,11 @@ void MacroAssembler::AllocateAsciiString(Register result, TAG_OBJECT); // Set the map, length and hash field. - LoadRoot(scratch1, Heap::kAsciiStringMapRootIndex); - mov(scratch1, Operand(Factory::ascii_string_map())); - str(length, FieldMemOperand(result, String::kLengthOffset)); - str(scratch1, FieldMemOperand(result, HeapObject::kMapOffset)); - mov(scratch2, Operand(String::kEmptyHashField)); - str(scratch2, FieldMemOperand(result, String::kHashFieldOffset)); + InitializeNewString(result, + length, + Heap::kAsciiStringMapRootIndex, + scratch1, + scratch2); } @@ -1108,11 +1121,12 @@ void MacroAssembler::AllocateTwoByteConsString(Register result, scratch2, gc_required, TAG_OBJECT); - LoadRoot(scratch1, Heap::kConsStringMapRootIndex); - mov(scratch2, Operand(String::kEmptyHashField)); - str(length, FieldMemOperand(result, String::kLengthOffset)); - str(scratch1, FieldMemOperand(result, HeapObject::kMapOffset)); - str(scratch2, FieldMemOperand(result, String::kHashFieldOffset)); + + InitializeNewString(result, + length, + Heap::kConsStringMapRootIndex, + scratch1, + scratch2); } @@ -1127,11 +1141,12 @@ void MacroAssembler::AllocateAsciiConsString(Register result, scratch2, gc_required, TAG_OBJECT); - LoadRoot(scratch1, Heap::kConsAsciiStringMapRootIndex); - mov(scratch2, Operand(String::kEmptyHashField)); - str(length, FieldMemOperand(result, String::kLengthOffset)); - str(scratch1, FieldMemOperand(result, HeapObject::kMapOffset)); - str(scratch2, FieldMemOperand(result, String::kHashFieldOffset)); + + InitializeNewString(result, + length, + Heap::kConsAsciiStringMapRootIndex, + scratch1, + scratch2); } diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h index f252ae9421..2ec7a39eab 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h @@ -572,6 +572,12 @@ class MacroAssembler: public Assembler { void EnterFrame(StackFrame::Type type); void LeaveFrame(StackFrame::Type type); + void InitializeNewString(Register string, + Register length, + Heap::RootListIndex map_index, + Register scratch1, + Register scratch2); + bool generating_stub_; bool allow_stub_calls_; // This handle will be patched with the code object on installation. diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc index fd0d24859d..fbccbab457 100644 --- a/src/arm/stub-cache-arm.cc +++ b/src/arm/stub-cache-arm.cc @@ -229,7 +229,6 @@ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, // Load length directly from the string. __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset)); - __ mov(r0, Operand(r0, LSL, kSmiTagSize)); __ Ret(); // Check if the object is a JSValue wrapper. @@ -241,7 +240,6 @@ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, __ ldr(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset)); GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss); __ ldr(r0, FieldMemOperand(scratch1, String::kLengthOffset)); - __ mov(r0, Operand(r0, LSL, kSmiTagSize)); __ Ret(); } diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index d426aaa06d..23e7c6ea57 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -2694,7 +2694,7 @@ void CodeGenerator::Comparison(AstNode* node, if (cc == equal) { Label comparison_done; __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset), - Immediate(1)); + Immediate(Smi::FromInt(1))); __ j(not_equal, &comparison_done); uint8_t char_value = static_cast(String::cast(*right_val)->Get(0)); @@ -2704,6 +2704,7 @@ void CodeGenerator::Comparison(AstNode* node, } else { __ mov(temp2.reg(), FieldOperand(left_side.reg(), String::kLengthOffset)); + __ SmiUntag(temp2.reg()); __ sub(Operand(temp2.reg()), Immediate(1)); Label comparison; // If the length is 0 then the subtraction gave -1 which compares less @@ -2723,7 +2724,7 @@ void CodeGenerator::Comparison(AstNode* node, // If the first character is the same then the long string sorts after // the short one. __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset), - Immediate(1)); + Immediate(Smi::FromInt(1))); __ bind(&characters_were_different); } temp2.Unuse(); @@ -8940,6 +8941,7 @@ void ToBooleanStub::Generate(MacroAssembler* masm) { __ cmp(ecx, FIRST_NONSTRING_TYPE); __ j(above_equal, ¬_string); __ mov(edx, FieldOperand(eax, String::kLengthOffset)); + ASSERT(kSmiTag == 0); __ test(edx, Operand(edx)); __ j(zero, &false_result); __ jmp(&true_result); @@ -10896,15 +10898,16 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { // Get the length of the string to ebx. __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); - // ebx: Length of subject string + // ebx: Length of subject string as a smi // ecx: RegExp data (FixedArray) // edx: Number of capture registers // Check that the third argument is a positive smi less than the subject // string length. A negative value will be greater (unsigned comparison). __ mov(eax, Operand(esp, kPreviousIndexOffset)); - __ SmiUntag(eax); + __ test(eax, Immediate(kSmiTagMask)); + __ j(zero, &runtime); __ cmp(eax, Operand(ebx)); - __ j(above, &runtime); + __ j(above_equal, &runtime); // ecx: RegExp data (FixedArray) // edx: Number of capture registers @@ -11027,6 +11030,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ test(edi, Operand(edi)); __ mov(edi, FieldOperand(eax, String::kLengthOffset)); __ j(zero, &setup_two_byte); + __ SmiUntag(edi); __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); @@ -11034,7 +11038,8 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ jmp(&setup_rest); __ bind(&setup_two_byte); - __ lea(ecx, FieldOperand(eax, edi, times_2, SeqTwoByteString::kHeaderSize)); + ASSERT(kSmiTag == 0 && kSmiTagSize == 1); // edi is smi (powered by 2). + __ lea(ecx, FieldOperand(eax, edi, times_1, SeqTwoByteString::kHeaderSize)); __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. @@ -12197,12 +12202,8 @@ void StringHelper::GenerateFastCharCodeAt(MacroAssembler* masm, __ test(index, Immediate(kSmiTagMask)); __ j(not_zero, index_not_smi); - // Put untagged index into scratch register. - __ mov(scratch, index); - __ SmiUntag(scratch); - // Check for index out of range. - __ cmp(scratch, FieldOperand(object, String::kLengthOffset)); + __ cmp(index, FieldOperand(object, String::kLengthOffset)); __ j(above_equal, index_out_of_range); __ bind(&try_again_with_new_string); @@ -12224,8 +12225,9 @@ void StringHelper::GenerateFastCharCodeAt(MacroAssembler* masm, // 2-byte string. // Load the 2-byte character code into the result register. + ASSERT(kSmiTag == 0 && kSmiTagSize == 1); // index is smi (powered by 2). __ movzx_w(result, FieldOperand(object, - scratch, times_2, + index, times_1, SeqTwoByteString::kHeaderSize)); __ jmp(&got_char_code); @@ -12251,6 +12253,10 @@ void StringHelper::GenerateFastCharCodeAt(MacroAssembler* masm, // ASCII string. __ bind(&ascii_string); + // Put untagged index into scratch register. + __ mov(scratch, index); + __ SmiUntag(scratch); + // Load the byte into the result register. __ movzx_b(result, FieldOperand(object, scratch, times_1, @@ -12341,6 +12347,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Check if either of the strings are empty. In that case return the other. Label second_not_zero_length, both_not_zero_length; __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); + ASSERT(kSmiTag == 0); __ test(ecx, Operand(ecx)); __ j(not_zero, &second_not_zero_length); // Second string is empty, result is first string which is already in eax. @@ -12348,6 +12355,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ ret(2 * kPointerSize); __ bind(&second_not_zero_length); __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); + ASSERT(kSmiTag == 0); __ test(ebx, Operand(ebx)); __ j(not_zero, &both_not_zero_length); // First string is empty, result is second string which is in edx. @@ -12357,16 +12365,19 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Both strings are non-empty. // eax: first string - // ebx: length of first string - // ecx: length of second string + // ebx: length of first string as a smi + // ecx: length of second string as a smi // edx: second string // Look at the length of the result of adding the two strings. Label string_add_flat_result, longer_than_two; __ bind(&both_not_zero_length); __ add(ebx, Operand(ecx)); + ASSERT(Smi::kMaxValue == String::kMaxLength); + // Handle exceptionally long strings in the runtime system. + __ j(overflow, &string_add_runtime); // Use the runtime system when adding two one character strings, as it // contains optimizations for this specific case using the symbol table. - __ cmp(ebx, 2); + __ cmp(Operand(ebx), Immediate(Smi::FromInt(2))); __ j(not_equal, &longer_than_two); // Check that both strings are non-external ascii strings. @@ -12386,17 +12397,13 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ ret(2 * kPointerSize); __ bind(&make_two_character_string); - __ Set(ebx, Immediate(2)); + __ Set(ebx, Immediate(Smi::FromInt(2))); __ jmp(&make_flat_ascii_string); __ bind(&longer_than_two); // Check if resulting string will be flat. - __ cmp(ebx, String::kMinNonFlatLength); + __ cmp(Operand(ebx), Immediate(Smi::FromInt(String::kMinNonFlatLength))); __ j(below, &string_add_flat_result); - // Handle exceptionally long strings in the runtime system. - ASSERT((String::kMaxLength & 0x80000000) == 0); - __ cmp(ebx, String::kMaxLength); - __ j(above, &string_add_runtime); // If result is not supposed to be flat allocate a cons string object. If both // strings are ascii the result is an ascii cons string. @@ -12413,6 +12420,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime); __ bind(&allocated); // Fill the fields of the cons string. + if (FLAG_debug_code) __ AbortIfNotSmi(ebx); __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx); __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset), Immediate(String::kEmptyHashField)); @@ -12429,7 +12437,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Handle creating a flat result. First check that both strings are not // external strings. // eax: first string - // ebx: length of resulting flat string + // ebx: length of resulting flat string as a smi // edx: second string __ bind(&string_add_flat_result); __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); @@ -12444,7 +12452,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ j(equal, &string_add_runtime); // Now check if both strings are ascii strings. // eax: first string - // ebx: length of resulting flat string + // ebx: length of resulting flat string as a smi // edx: second string Label non_ascii_string_add_flat_result; __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); @@ -12459,7 +12467,8 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ bind(&make_flat_ascii_string); // Both strings are ascii strings. As they are short they are both flat. - // ebx: length of resulting flat string + // ebx: length of resulting flat string as a smi + __ SmiUntag(ebx); __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime); // eax: result string __ mov(ecx, eax); @@ -12468,6 +12477,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Load first argument and locate first character. __ mov(edx, Operand(esp, 2 * kPointerSize)); __ mov(edi, FieldOperand(edx, String::kLengthOffset)); + __ SmiUntag(edi); __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); // eax: result string // ecx: first character of result @@ -12477,6 +12487,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Load second argument and locate first character. __ mov(edx, Operand(esp, 1 * kPointerSize)); __ mov(edi, FieldOperand(edx, String::kLengthOffset)); + __ SmiUntag(edi); __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); // eax: result string // ecx: next character of result @@ -12488,7 +12499,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Handle creating a flat two byte result. // eax: first string - known to be two byte - // ebx: length of resulting flat string + // ebx: length of resulting flat string as a smi // edx: second string __ bind(&non_ascii_string_add_flat_result); __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); @@ -12497,6 +12508,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ j(not_zero, &string_add_runtime); // Both strings are two byte strings. As they are short they are both // flat. + __ SmiUntag(ebx); __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime); // eax: result string __ mov(ecx, eax); @@ -12506,6 +12518,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Load first argument and locate first character. __ mov(edx, Operand(esp, 2 * kPointerSize)); __ mov(edi, FieldOperand(edx, String::kLengthOffset)); + __ SmiUntag(edi); __ add(Operand(edx), Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); // eax: result string @@ -12516,6 +12529,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Load second argument and locate first character. __ mov(edx, Operand(esp, 1 * kPointerSize)); __ mov(edi, FieldOperand(edx, String::kLengthOffset)); + __ SmiUntag(edi); __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); // eax: result string // ecx: next character of result @@ -12700,7 +12714,8 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, __ j(equal, not_found); // If length is not 2 the string is not a candidate. - __ cmp(FieldOperand(candidate, String::kLengthOffset), Immediate(2)); + __ cmp(FieldOperand(candidate, String::kLengthOffset), + Immediate(Smi::FromInt(2))); __ j(not_equal, &next_probe[i]); // As we are out of registers save the mask on the stack and use that @@ -12969,6 +12984,7 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, // Change index to run from -min_length to -1 by adding min_length // to string start. This means that loop ends when index reaches zero, // which doesn't need an additional compare. + __ SmiUntag(min_length); __ lea(left, FieldOperand(left, min_length, times_1, diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index 0deec8f269..a7d2834520 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -910,7 +910,9 @@ void MacroAssembler::AllocateTwoByteString(Register result, // Set the map, length and hash field. mov(FieldOperand(result, HeapObject::kMapOffset), Immediate(Factory::string_map())); - mov(FieldOperand(result, String::kLengthOffset), length); + mov(scratch1, length); + SmiTag(scratch1); + mov(FieldOperand(result, String::kLengthOffset), scratch1); mov(FieldOperand(result, String::kHashFieldOffset), Immediate(String::kEmptyHashField)); } @@ -943,7 +945,9 @@ void MacroAssembler::AllocateAsciiString(Register result, // Set the map, length and hash field. mov(FieldOperand(result, HeapObject::kMapOffset), Immediate(Factory::ascii_string_map())); - mov(FieldOperand(result, String::kLengthOffset), length); + mov(scratch1, length); + SmiTag(scratch1); + mov(FieldOperand(result, String::kLengthOffset), scratch1); mov(FieldOperand(result, String::kHashFieldOffset), Immediate(String::kEmptyHashField)); } diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc index 86e86e1d5f..809228c7ec 100644 --- a/src/ia32/stub-cache-ia32.cc +++ b/src/ia32/stub-cache-ia32.cc @@ -221,7 +221,6 @@ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, // Load length from the string and convert to a smi. __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); - __ SmiTag(eax); __ ret(0); // Check if the object is a JSValue wrapper. @@ -234,7 +233,6 @@ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); GenerateStringCheck(masm, scratch2, scratch1, miss, miss); __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); - __ SmiTag(eax); __ ret(0); } diff --git a/src/objects-inl.h b/src/objects-inl.h index 59fdd86507..f1e8596034 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -1651,7 +1651,7 @@ HashTable* HashTable::cast(Object* obj) { INT_ACCESSORS(Array, length, kLengthOffset) -INT_ACCESSORS(String, length, kLengthOffset) +SMI_ACCESSORS(String, length, kLengthOffset) uint32_t String::hash_field() { @@ -1773,14 +1773,12 @@ void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) { int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) { - uint32_t length = READ_INT_FIELD(this, kLengthOffset); - return SizeFor(length); + return SizeFor(length()); } int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) { - uint32_t length = READ_INT_FIELD(this, kLengthOffset); - return SizeFor(length); + return SizeFor(length()); } diff --git a/src/objects.h b/src/objects.h index 48be90217e..ad40175605 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4077,7 +4077,7 @@ class String: public HeapObject { // Layout description. static const int kLengthOffset = HeapObject::kHeaderSize; - static const int kHashFieldOffset = kLengthOffset + kIntSize; + static const int kHashFieldOffset = kLengthOffset + kPointerSize; static const int kSize = kHashFieldOffset + kIntSize; // Notice: kSize is not pointer-size aligned if pointers are 64-bit. diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index faff015022..39f543df56 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -5866,8 +5866,8 @@ void CodeGenerator::Comparison(AstNode* node, // Test string equality and comparison. if (cc == equal) { Label comparison_done; - __ cmpl(FieldOperand(left_side.reg(), String::kLengthOffset), - Immediate(1)); + __ SmiCompare(FieldOperand(left_side.reg(), String::kLengthOffset), + Smi::FromInt(1)); __ j(not_equal, &comparison_done); uint8_t char_value = static_cast(String::cast(*right_val)->Get(0)); @@ -5875,9 +5875,9 @@ void CodeGenerator::Comparison(AstNode* node, Immediate(char_value)); __ bind(&comparison_done); } else { - __ movl(temp2.reg(), + __ movq(temp2.reg(), FieldOperand(left_side.reg(), String::kLengthOffset)); - __ subl(temp2.reg(), Immediate(1)); + __ SmiSubConstant(temp2.reg(), temp2.reg(), Smi::FromInt(1)); Label comparison; // If the length is 0 then the subtraction gave -1 which compares less // than any character. @@ -5895,8 +5895,8 @@ void CodeGenerator::Comparison(AstNode* node, __ j(not_equal, &characters_were_different); // If the first character is the same then the long string sorts after // the short one. - __ cmpl(FieldOperand(left_side.reg(), String::kLengthOffset), - Immediate(1)); + __ SmiCompare(FieldOperand(left_side.reg(), String::kLengthOffset), + Smi::FromInt(1)); __ bind(&characters_were_different); } temp2.Unuse(); @@ -7515,8 +7515,8 @@ void ToBooleanStub::Generate(MacroAssembler* masm) { // String value => false iff empty. __ cmpq(rcx, Immediate(FIRST_NONSTRING_TYPE)); __ j(above_equal, ¬_string); - __ movl(rdx, FieldOperand(rax, String::kLengthOffset)); - __ testl(rdx, rdx); + __ movq(rdx, FieldOperand(rax, String::kLengthOffset)); + __ SmiTest(rdx); __ j(zero, &false_result); __ jmp(&true_result); @@ -8123,17 +8123,17 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); __ j(NegateCondition(is_string), &runtime); // Get the length of the string to rbx. - __ movl(rbx, FieldOperand(rax, String::kLengthOffset)); + __ movq(rbx, FieldOperand(rax, String::kLengthOffset)); - // rbx: Length of subject string + // rbx: Length of subject string as smi // rcx: RegExp data (FixedArray) // rdx: Number of capture registers // Check that the third argument is a positive smi less than the string // length. A negative value will be greater (unsigned comparison). __ movq(rax, Operand(rsp, kPreviousIndexOffset)); - __ SmiToInteger32(rax, rax); - __ cmpl(rax, rbx); - __ j(above, &runtime); + __ JumpIfNotSmi(rax, &runtime); + __ SmiCompare(rax, rbx); + __ j(above_equal, &runtime); // rcx: RegExp data (FixedArray) // rdx: Number of capture registers @@ -8286,12 +8286,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { // Argument 3: Start of string data Label setup_two_byte, setup_rest; __ testb(rdi, rdi); - __ movl(rdi, FieldOperand(rax, String::kLengthOffset)); + __ movq(rdi, FieldOperand(rax, String::kLengthOffset)); __ j(zero, &setup_two_byte); + __ SmiToInteger32(rdi, rdi); __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize)); __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize)); __ jmp(&setup_rest); __ bind(&setup_two_byte); + __ SmiToInteger32(rdi, rdi); __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize)); __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize)); @@ -10456,11 +10458,8 @@ void StringHelper::GenerateFastCharCodeAt(MacroAssembler* masm, // If the index is non-smi trigger the non-smi case. __ JumpIfNotSmi(index, index_not_smi); - // Put untagged index into scratch register. - __ SmiToInteger32(scratch, index); - // Check for index out of range. - __ cmpl(scratch, FieldOperand(object, String::kLengthOffset)); + __ SmiCompare(index, FieldOperand(object, String::kLengthOffset)); __ j(above_equal, index_out_of_range); __ bind(&try_again_with_new_string); @@ -10475,6 +10474,9 @@ void StringHelper::GenerateFastCharCodeAt(MacroAssembler* masm, __ testb(result, Immediate(kStringRepresentationMask)); __ j(not_zero, ¬_a_flat_string); + // Put untagged index into scratch register. + __ SmiToInteger32(scratch, index); + // Check for 1-byte or 2-byte string. ASSERT_EQ(0, kTwoByteStringTag); __ testb(result, Immediate(kStringEncodingMask)); @@ -10596,15 +10598,15 @@ void StringAddStub::Generate(MacroAssembler* masm) { // rdx: second string // Check if either of the strings are empty. In that case return the other. Label second_not_zero_length, both_not_zero_length; - __ movl(rcx, FieldOperand(rdx, String::kLengthOffset)); - __ testl(rcx, rcx); + __ movq(rcx, FieldOperand(rdx, String::kLengthOffset)); + __ SmiTest(rcx); __ j(not_zero, &second_not_zero_length); // Second string is empty, result is first string which is already in rax. __ IncrementCounter(&Counters::string_add_native, 1); __ ret(2 * kPointerSize); __ bind(&second_not_zero_length); - __ movl(rbx, FieldOperand(rax, String::kLengthOffset)); - __ testl(rbx, rbx); + __ movq(rbx, FieldOperand(rax, String::kLengthOffset)); + __ SmiTest(rbx); __ j(not_zero, &both_not_zero_length); // First string is empty, result is second string which is in rdx. __ movq(rax, rdx); @@ -10632,10 +10634,11 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset)); // Look at the length of the result of adding the two strings. - __ addl(rbx, rcx); + ASSERT(String::kMaxLength <= Smi::kMaxValue / 2); + __ SmiAdd(rbx, rbx, rcx, NULL); // Use the runtime system when adding two one character strings, as it // contains optimizations for this specific case using the symbol table. - __ cmpl(rbx, Immediate(2)); + __ SmiCompare(rbx, Smi::FromInt(2)); __ j(not_equal, &longer_than_two); // Check that both strings are non-external ascii strings. @@ -10660,11 +10663,11 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ bind(&longer_than_two); // Check if resulting string will be flat. - __ cmpl(rbx, Immediate(String::kMinNonFlatLength)); + __ SmiCompare(rbx, Smi::FromInt(String::kMinNonFlatLength)); __ j(below, &string_add_flat_result); // Handle exceptionally long strings in the runtime system. ASSERT((String::kMaxLength & 0x80000000) == 0); - __ cmpl(rbx, Immediate(String::kMaxLength)); + __ SmiCompare(rbx, Smi::FromInt(String::kMaxLength)); __ j(above, &string_add_runtime); // If result is not supposed to be flat, allocate a cons string object. If @@ -10684,7 +10687,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime); __ bind(&allocated); // Fill the fields of the cons string. - __ movl(FieldOperand(rcx, ConsString::kLengthOffset), rbx); + __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx); __ movl(FieldOperand(rcx, ConsString::kHashFieldOffset), Immediate(String::kEmptyHashField)); __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax); @@ -10700,11 +10703,12 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Handle creating a flat result. First check that both strings are not // external strings. // rax: first string - // ebx: length of resulting flat string + // ebx: length of resulting flat string as smi // rdx: second string // r8: instance type of first string // r9: instance type of first string __ bind(&string_add_flat_result); + __ SmiToInteger32(rbx, rbx); __ movl(rcx, r8); __ and_(rcx, Immediate(kStringRepresentationMask)); __ cmpl(rcx, Immediate(kExternalStringTag)); @@ -10734,7 +10738,8 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Locate first character of result. __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); // Locate first character of first argument - __ movl(rdi, FieldOperand(rax, String::kLengthOffset)); + __ movq(rdi, FieldOperand(rax, String::kLengthOffset)); + __ SmiToInteger32(rdi, rdi); __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); // rax: first char of first argument // rbx: result string @@ -10743,7 +10748,8 @@ void StringAddStub::Generate(MacroAssembler* masm) { // rdi: length of first argument StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, true); // Locate first character of second argument. - __ movl(rdi, FieldOperand(rdx, String::kLengthOffset)); + __ movq(rdi, FieldOperand(rdx, String::kLengthOffset)); + __ SmiToInteger32(rdi, rdi); __ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); // rbx: result string // rcx: next character of result @@ -10771,7 +10777,8 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Locate first character of result. __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); // Locate first character of first argument. - __ movl(rdi, FieldOperand(rax, String::kLengthOffset)); + __ movq(rdi, FieldOperand(rax, String::kLengthOffset)); + __ SmiToInteger32(rdi, rdi); __ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); // rax: first char of first argument // rbx: result string @@ -10780,7 +10787,8 @@ void StringAddStub::Generate(MacroAssembler* masm) { // rdi: length of first argument StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, false); // Locate first character of second argument. - __ movl(rdi, FieldOperand(rdx, String::kLengthOffset)); + __ movq(rdi, FieldOperand(rdx, String::kLengthOffset)); + __ SmiToInteger32(rdi, rdi); __ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); // rbx: result string // rcx: next character of result @@ -10962,7 +10970,8 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, __ j(equal, not_found); // If length is not 2 the string is not a candidate. - __ cmpl(FieldOperand(candidate, String::kLengthOffset), Immediate(2)); + __ SmiCompare(FieldOperand(candidate, String::kLengthOffset), + Smi::FromInt(2)); __ j(not_equal, &next_probe[i]); // We use kScratchRegister as a temporary register in assumption that @@ -11206,9 +11215,12 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, ASSERT(String::kMaxLength < 0x7fffffff); // Find minimum length and length difference. - __ movl(scratch1, FieldOperand(left, String::kLengthOffset)); - __ movl(scratch4, scratch1); - __ subl(scratch4, FieldOperand(right, String::kLengthOffset)); + __ movq(scratch1, FieldOperand(left, String::kLengthOffset)); + __ movq(scratch4, scratch1); + __ SmiSub(scratch4, + scratch4, + FieldOperand(right, String::kLengthOffset), + NULL); // Register scratch4 now holds left.length - right.length. const Register length_difference = scratch4; Label left_shorter; @@ -11216,16 +11228,18 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, // The right string isn't longer that the left one. // Get the right string's length by subtracting the (non-negative) difference // from the left string's length. - __ subl(scratch1, length_difference); + __ SmiSub(scratch1, scratch1, length_difference, NULL); __ bind(&left_shorter); // Register scratch1 now holds Min(left.length, right.length). const Register min_length = scratch1; Label compare_lengths; // If min-length is zero, go directly to comparing lengths. - __ testl(min_length, min_length); + __ SmiTest(min_length); __ j(zero, &compare_lengths); + __ SmiToInteger32(min_length, min_length); + // Registers scratch2 and scratch3 are free. Label result_not_equal; Label loop; @@ -11256,7 +11270,7 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, // Completed loop without finding different characters. // Compare lengths (precomputed). __ bind(&compare_lengths); - __ testl(length_difference, length_difference); + __ SmiTest(length_difference); __ j(not_zero, &result_not_equal); // Result is EQUAL. diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 23ba976011..a1976ec3f3 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -596,6 +596,11 @@ void MacroAssembler::SmiCompare(Register dst, Smi* src) { } +void MacroAssembler::SmiCompare(Register dst, const Operand& src) { + cmpq(dst, src); +} + + void MacroAssembler::SmiCompare(const Operand& dst, Register src) { cmpq(dst, src); } @@ -731,7 +736,17 @@ void MacroAssembler::SmiAdd(Register dst, Register src2, Label* on_not_smi_result) { ASSERT(!dst.is(src2)); - if (dst.is(src1)) { + if (on_not_smi_result == NULL) { + // No overflow checking. Use only when it's known that + // overflowing is impossible. + if (dst.is(src1)) { + addq(dst, src2); + } else { + movq(dst, src1); + addq(dst, src2); + } + Assert(no_overflow, "Smi addition onverflow"); + } else if (dst.is(src1)) { addq(dst, src2); Label smi_result; j(no_overflow, &smi_result); @@ -778,6 +793,35 @@ void MacroAssembler::SmiSub(Register dst, } +void MacroAssembler::SmiSub(Register dst, + Register src1, + Operand const& src2, + Label* on_not_smi_result) { + if (on_not_smi_result == NULL) { + // No overflow checking. Use only when it's known that + // overflowing is impossible (e.g., subtracting two positive smis). + if (dst.is(src1)) { + subq(dst, src2); + } else { + movq(dst, src1); + subq(dst, src2); + } + Assert(no_overflow, "Smi substraction onverflow"); + } else if (dst.is(src1)) { + subq(dst, src2); + Label smi_result; + j(no_overflow, &smi_result); + // Restore src1. + addq(src1, src2); + jmp(on_not_smi_result); + bind(&smi_result); + } else { + movq(dst, src1); + subq(dst, src2); + j(overflow, on_not_smi_result); + } +} + void MacroAssembler::SmiMul(Register dst, Register src1, Register src2, @@ -2526,11 +2570,16 @@ void MacroAssembler::AllocateTwoByteString(Register result, Label* gc_required) { // Calculate the number of bytes needed for the characters in the string while // observing object alignment. - ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); + const int kHeaderAlignment = SeqTwoByteString::kHeaderSize & + kObjectAlignmentMask; ASSERT(kShortSize == 2); // scratch1 = length * 2 + kObjectAlignmentMask. - lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask)); + lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask + + kHeaderAlignment)); and_(scratch1, Immediate(~kObjectAlignmentMask)); + if (kHeaderAlignment > 0) { + subq(scratch1, Immediate(kHeaderAlignment)); + } // Allocate two byte string in new space. AllocateInNewSpace(SeqTwoByteString::kHeaderSize, @@ -2545,7 +2594,8 @@ void MacroAssembler::AllocateTwoByteString(Register result, // Set the map, length and hash field. LoadRoot(kScratchRegister, Heap::kStringMapRootIndex); movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); - movl(FieldOperand(result, String::kLengthOffset), length); + Integer32ToSmi(scratch1, length); + movq(FieldOperand(result, String::kLengthOffset), scratch1); movl(FieldOperand(result, String::kHashFieldOffset), Immediate(String::kEmptyHashField)); } @@ -2559,11 +2609,15 @@ void MacroAssembler::AllocateAsciiString(Register result, Label* gc_required) { // Calculate the number of bytes needed for the characters in the string while // observing object alignment. - ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); + const int kHeaderAlignment = SeqAsciiString::kHeaderSize & + kObjectAlignmentMask; movl(scratch1, length); ASSERT(kCharSize == 1); - addq(scratch1, Immediate(kObjectAlignmentMask)); + addq(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment)); and_(scratch1, Immediate(~kObjectAlignmentMask)); + if (kHeaderAlignment > 0) { + subq(scratch1, Immediate(kHeaderAlignment)); + } // Allocate ascii string in new space. AllocateInNewSpace(SeqAsciiString::kHeaderSize, @@ -2578,7 +2632,8 @@ void MacroAssembler::AllocateAsciiString(Register result, // Set the map, length and hash field. LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex); movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); - movl(FieldOperand(result, String::kLengthOffset), length); + Integer32ToSmi(scratch1, length); + movq(FieldOperand(result, String::kLengthOffset), scratch1); movl(FieldOperand(result, String::kHashFieldOffset), Immediate(String::kEmptyHashField)); } diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h index 60e423acd5..32e1f4972f 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h @@ -211,6 +211,7 @@ class MacroAssembler: public Assembler { // Simple comparison of smis. void SmiCompare(Register dst, Register src); void SmiCompare(Register dst, Smi* src); + void SmiCompare(Register dst, const Operand& src); void SmiCompare(const Operand& dst, Register src); void SmiCompare(const Operand& dst, Smi* src); // Sets sign and zero flags depending on value of smi in register. @@ -301,7 +302,8 @@ class MacroAssembler: public Assembler { Label* on_not_smi_result); // Subtract an integer constant from a tagged smi, giving a tagged smi as - // result. No testing on the result is done. + // result. No testing on the result is done. Sets the N and Z flags + // based on the value of the resulting integer. void SmiSubConstant(Register dst, Register src, Smi* constant); // Subtract an integer constant from a tagged smi, giving a tagged smi as @@ -333,6 +335,11 @@ class MacroAssembler: public Assembler { Register src2, Label* on_not_smi_result); + void SmiSub(Register dst, + Register src1, + Operand const& src2, + Label* on_not_smi_result); + // Multiplies smi values and return the result as a smi, // if possible. // If dst is src1, then src1 will be destroyed, even if diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc index 918b72f494..7d4410cb00 100644 --- a/src/x64/stub-cache-x64.cc +++ b/src/x64/stub-cache-x64.cc @@ -327,8 +327,7 @@ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper); // Load length directly from the string. - __ movl(rax, FieldOperand(receiver, String::kLengthOffset)); - __ Integer32ToSmi(rax, rax); + __ movq(rax, FieldOperand(receiver, String::kLengthOffset)); __ ret(0); // Check if the object is a JSValue wrapper. @@ -340,8 +339,7 @@ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, // directly if it is. __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); GenerateStringCheck(masm, scratch2, scratch1, miss, miss); - __ movl(rax, FieldOperand(scratch2, String::kLengthOffset)); - __ Integer32ToSmi(rax, rax); + __ movq(rax, FieldOperand(scratch2, String::kLengthOffset)); __ ret(0); } diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc index 54e69a1d54..c4c8a4579f 100644 --- a/test/cctest/test-serialize.cc +++ b/test/cctest/test-serialize.cc @@ -573,7 +573,8 @@ TEST(LinearAllocation) { FixedArray::kHeaderSize + kSmallFixedArrayLength * kPointerSize; const int kSmallStringLength = 16; const int kSmallStringSize = - SeqAsciiString::kHeaderSize + kSmallStringLength; + (SeqAsciiString::kHeaderSize + kSmallStringLength + + kObjectAlignmentMask) & ~kObjectAlignmentMask; const int kMapSize = Map::kSize; Object* new_last = NULL;