Revision: 4581
Author: [email protected]
Date: Tue May 4 07:49:50 2010
Log: 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
http://code.google.com/p/v8/source/detail?r=4581
Modified:
/branches/bleeding_edge/include/v8.h
/branches/bleeding_edge/src/arm/codegen-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.h
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
/branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
/branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/x64/codegen-x64.cc
/branches/bleeding_edge/src/x64/macro-assembler-x64.cc
/branches/bleeding_edge/src/x64/macro-assembler-x64.h
/branches/bleeding_edge/src/x64/stub-cache-x64.cc
/branches/bleeding_edge/test/cctest/test-serialize.cc
=======================================
--- /branches/bleeding_edge/include/v8.h Tue Apr 27 06:02:23 2010
+++ /branches/bleeding_edge/include/v8.h Tue May 4 07:49:50 2010
@@ -3014,7 +3014,7 @@
// Internal constants for 64-bit systems.
template <> struct InternalConstants<8> {
- static const int kStringResourceOffset = 2 * sizeof(void*);
+ static const int kStringResourceOffset = 3 * sizeof(void*);
};
/**
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc Tue May 4 04:06:59 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc Tue May 4 07:49:50 2010
@@ -8498,14 +8498,16 @@
__ 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
// 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 @@
__ 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
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Tue May 4
04:06:59 2010
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Tue May 4
07:49:50 2010
@@ -422,6 +422,20 @@
}
#endif
}
+
+
+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() {
@@ -1054,11 +1068,11 @@
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 @@
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 @@
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 @@
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);
}
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Tue May 4
04:06:59 2010
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Tue May 4
07:49:50 2010
@@ -572,6 +572,12 @@
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.
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Thu Apr 29 06:58:39
2010
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Tue May 4 07:49:50
2010
@@ -229,7 +229,6 @@
// 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 @@
__ 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();
}
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue May 4 04:17:45
2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue May 4 07:49:50
2010
@@ -2694,7 +2694,7 @@
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<uint8_t>(String::cast(*right_val)->Get(0));
@@ -2704,6 +2704,7 @@
} 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 @@
// 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 @@
__ 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 @@
// 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
// 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 @@
// 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 @@
// 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 @@
__ 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 @@
// 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 @@
__ 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 @@
__ 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 @@
// 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 @@
__ 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 @@
__ 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 @@
// 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 @@
// 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 @@
// 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 @@
__ 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 @@
// 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 @@
// 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 @@
__ 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 @@
// 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,
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Tue May 4
04:06:59 2010
+++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Tue May 4
07:49:50 2010
@@ -910,7 +910,9 @@
// 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 @@
// 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));
}
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue May 4 06:23:58
2010
+++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue May 4 07:49:50
2010
@@ -221,7 +221,6 @@
// 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 @@
__ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
__ mov(eax, FieldOperand(scratch2, String::kLengthOffset));
- __ SmiTag(eax);
__ ret(0);
}
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Wed Apr 28 05:05:40 2010
+++ /branches/bleeding_edge/src/objects-inl.h Tue May 4 07:49:50 2010
@@ -1651,7 +1651,7 @@
INT_ACCESSORS(Array, length, kLengthOffset)
-INT_ACCESSORS(String, length, kLengthOffset)
+SMI_ACCESSORS(String, length, kLengthOffset)
uint32_t String::hash_field() {
@@ -1773,14 +1773,12 @@
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());
}
=======================================
--- /branches/bleeding_edge/src/objects.h Mon May 3 03:43:49 2010
+++ /branches/bleeding_edge/src/objects.h Tue May 4 07:49:50 2010
@@ -4077,7 +4077,7 @@
// 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.
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc Tue May 4 06:23:58 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc Tue May 4 07:49:50 2010
@@ -5866,8 +5866,8 @@
// 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<uint8_t>(String::cast(*right_val)->Get(0));
@@ -5875,9 +5875,9 @@
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 @@
__ 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 @@
// 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 @@
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));
-
- // rbx: Length of subject string
+ __ movq(rbx, FieldOperand(rax, String::kLengthOffset));
+
+ // 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 @@
// 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 @@
// 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 @@
__ 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 @@
// 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
__ 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 @@
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 @@
// 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 @@
// 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.
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Tue May 4
06:23:58 2010
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Tue May 4
07:49:50 2010
@@ -594,6 +594,11 @@
cmpq(dst, kScratchRegister);
}
}
+
+
+void MacroAssembler::SmiCompare(Register dst, const Operand& src) {
+ cmpq(dst, src);
+}
void MacroAssembler::SmiCompare(const Operand& dst, Register src) {
@@ -731,7 +736,17 @@
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);
@@ -777,6 +792,35 @@
}
}
+
+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,
@@ -2526,11 +2570,16 @@
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 @@
// 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 @@
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 @@
// 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));
}
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Tue May 4
06:23:58 2010
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Tue May 4
07:49:50 2010
@@ -211,6 +211,7 @@
// 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 @@
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 @@
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
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Tue May 4 06:23:58
2010
+++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Tue May 4 07:49:50
2010
@@ -327,8 +327,7 @@
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 @@
// 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);
}
=======================================
--- /branches/bleeding_edge/test/cctest/test-serialize.cc Tue Mar 23
04:40:38 2010
+++ /branches/bleeding_edge/test/cctest/test-serialize.cc Tue May 4
07:49:50 2010
@@ -573,7 +573,8 @@
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;
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev