}
-static void Generate_LoadIC_ShortStringLength(MacroAssembler* masm) {
- LoadIC::GenerateShortStringLength(masm);
-}
-
-
-static void Generate_LoadIC_MediumStringLength(MacroAssembler* masm) {
- LoadIC::GenerateMediumStringLength(masm);
-}
-
-
-static void Generate_LoadIC_LongStringLength(MacroAssembler* masm) {
- LoadIC::GenerateLongStringLength(masm);
+static void Generate_LoadIC_StringLength(MacroAssembler* masm) {
+ LoadIC::GenerateStringLength(masm);
}
V(LoadIC_PreMonomorphic, LOAD_IC, PREMONOMORPHIC) \
V(LoadIC_Normal, LOAD_IC, MONOMORPHIC) \
V(LoadIC_ArrayLength, LOAD_IC, MONOMORPHIC) \
- V(LoadIC_ShortStringLength, LOAD_IC, MONOMORPHIC) \
- V(LoadIC_MediumStringLength, LOAD_IC, MONOMORPHIC) \
- V(LoadIC_LongStringLength, LOAD_IC, MONOMORPHIC) \
+ V(LoadIC_StringLength, LOAD_IC, MONOMORPHIC) \
V(LoadIC_FunctionPrototype, LOAD_IC, MONOMORPHIC) \
V(LoadIC_Megamorphic, LOAD_IC, MEGAMORPHIC) \
V(LoadIC_DebugBreak, LOAD_IC, DEBUG_BREAK) \
__ sar(ebx, kSmiTagSize);
__ bind(&try_again_with_new_string);
- // Get the type of the heap object into ecx.
+ // Get the type of the heap object into edi.
__ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
- __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));
+ __ movzx_b(edi, FieldOperand(edx, Map::kInstanceTypeOffset));
// We don't handle non-strings.
- __ test(ecx, Immediate(kIsNotStringMask));
+ __ test(edi, Immediate(kIsNotStringMask));
__ j(not_zero, &slow_case, not_taken);
+ // Here we make assumptions about the tag values and the shifts needed.
+ // See the comment in objects.h.
+ ASSERT(kLongStringTag == 0);
+ ASSERT(kMediumStringTag + String::kLongLengthShift ==
+ String::kMediumLengthShift);
+ ASSERT(kShortStringTag + String::kLongLengthShift ==
+ String::kShortLengthShift);
+ __ mov(ecx, Operand(edi));
+ __ and_(ecx, kStringSizeMask);
+ __ add(Operand(ecx), Immediate(String::kLongLengthShift));
// Get the length field.
__ mov(edx, FieldOperand(eax, String::kLengthOffset));
- Label long_string;
- Label medium_string;
- Label string_length_shifted;
- // The code assumes the tags are disjoint.
- ASSERT((kLongStringTag & kMediumStringTag) == 0);
- ASSERT(kShortStringTag == 0);
- __ test(ecx, Immediate(kLongStringTag));
- __ j(not_zero, &long_string, not_taken);
- __ test(ecx, Immediate(kMediumStringTag));
- __ j(not_zero, &medium_string, taken);
- // Short string.
- __ shr(edx, String::kShortLengthShift);
- __ jmp(&string_length_shifted);
-
- // Medium string.
- __ bind(&medium_string);
- __ shr(edx, String::kMediumLengthShift - String::kLongLengthShift);
- // Fall through to long string.
- __ bind(&long_string);
- __ shr(edx, String::kLongLengthShift);
-
- __ bind(&string_length_shifted);
- ASSERT(kSmiTag == 0);
+ __ shr(edx); // ecx is implicit operand.
// edx is now the length of the string.
// Check for index out of range.
// We need special handling for non-flat strings.
ASSERT(kSeqStringTag == 0);
- __ test(ecx, Immediate(kStringRepresentationMask));
+ __ test(edi, Immediate(kStringRepresentationMask));
__ j(not_zero, ¬_a_flat_string, not_taken);
// Check for 1-byte or 2-byte string.
- __ test(ecx, Immediate(kStringEncodingMask));
+ __ test(edi, Immediate(kStringEncodingMask));
__ j(not_zero, &ascii_string, taken);
// 2-byte string.
frame_->Push(eax);
__ jmp(&end);
-
// Handle non-flat strings.
__ bind(¬_a_flat_string);
- __ and_(ecx, kStringRepresentationMask);
- __ cmp(ecx, kConsStringTag);
+ __ and_(edi, kStringRepresentationMask);
+ __ cmp(edi, kConsStringTag);
__ j(not_equal, ¬_a_cons_string_either, not_taken);
// ConsString.
__ jmp(&try_again_with_new_string);
__ bind(¬_a_cons_string_either);
- __ cmp(ecx, kSlicedStringTag);
+ __ cmp(edi, kSlicedStringTag);
__ j(not_equal, &slow_case, not_taken);
// SlicedString.
}
-void LoadIC::GenerateShortStringLength(MacroAssembler* masm) {
+void LoadIC::GenerateStringLength(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
__ mov(eax, Operand(esp, kPointerSize));
- StubCompiler::GenerateLoadShortStringLength(masm, eax, edx, &miss);
- __ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
-}
-
-
-void LoadIC::GenerateMediumStringLength(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- ecx : name
- // -- esp[0] : return address
- // -- esp[4] : receiver
- // -----------------------------------
-
- Label miss;
-
- __ mov(eax, Operand(esp, kPointerSize));
-
- StubCompiler::GenerateLoadMediumStringLength(masm, eax, edx, &miss);
- __ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
-}
-
-
-void LoadIC::GenerateLongStringLength(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- ecx : name
- // -- esp[0] : return address
- // -- esp[4] : receiver
- // -----------------------------------
-
- Label miss;
-
- __ mov(eax, Operand(esp, kPointerSize));
-
- StubCompiler::GenerateLoadLongStringLength(masm, eax, edx, &miss);
+ StubCompiler::GenerateLoadStringLength(masm, eax, edx, &miss);
__ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
}
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
#endif
Code* target = NULL;
- if (object->IsShortString()) {
- target = Builtins::builtin(Builtins::LoadIC_ShortStringLength);
- } else if (object->IsMediumString()) {
- target = Builtins::builtin(Builtins::LoadIC_MediumStringLength);
- } else {
- ASSERT(object->IsLongString());
- target = Builtins::builtin(Builtins::LoadIC_LongStringLength);
- }
+ target = Builtins::builtin(Builtins::LoadIC_StringLength);
set_target(target);
StubCache::Set(*name, HeapObject::cast(*object)->map(), target);
return Smi::FromInt(String::cast(*object)->length());
if (object->IsString() && name->Equals(Heap::length_symbol())) {
Handle<String> string = Handle<String>::cast(object);
Object* code = NULL;
- if (string->IsShortString()) {
- code = StubCache::ComputeKeyedLoadShortStringLength(*name, *string);
- } else if (string->IsMediumString()) {
- code =
- StubCache::ComputeKeyedLoadMediumStringLength(*name, *string);
- } else {
- ASSERT(string->IsLongString());
- code = StubCache::ComputeKeyedLoadLongStringLength(*name, *string);
- }
+ code = StubCache::ComputeKeyedLoadStringLength(*name, *string);
if (code->IsFailure()) return code;
set_target(Code::cast(code));
#ifdef DEBUG
// Specialized code generator routines.
static void GenerateArrayLength(MacroAssembler* masm);
- static void GenerateShortStringLength(MacroAssembler* masm);
- static void GenerateMediumStringLength(MacroAssembler* masm);
- static void GenerateLongStringLength(MacroAssembler* masm);
+ static void GenerateStringLength(MacroAssembler* masm);
static void GenerateFunctionPrototype(MacroAssembler* masm);
private:
int String::length() {
uint32_t len = READ_INT_FIELD(this, kLengthOffset);
- switch (size_tag()) {
- case kShortStringTag:
- return len >> kShortLengthShift;
- case kMediumStringTag:
- return len >> kMediumLengthShift;
- case kLongStringTag:
- return len >> kLongLengthShift;
- default:
- break;
- }
- UNREACHABLE();
- return 0;
+ ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
+ ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
+ ASSERT(kLongStringTag == 0);
+
+ return len >> (size_tag() + kLongLengthShift);
}
void String::set_length(int value) {
- switch (size_tag()) {
- case kShortStringTag:
- WRITE_INT_FIELD(this, kLengthOffset, value << kShortLengthShift);
- break;
- case kMediumStringTag:
- WRITE_INT_FIELD(this, kLengthOffset, value << kMediumLengthShift);
- break;
- case kLongStringTag:
- WRITE_INT_FIELD(this, kLengthOffset, value << kLongLengthShift);
- break;
- default:
- UNREACHABLE();
- break;
- }
+ ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
+ ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
+ ASSERT(kLongStringTag == 0);
+
+ WRITE_INT_FIELD(this,
+ kLengthOffset,
+ value << (size_tag() + kLongLengthShift));
}
int SeqTwoByteString::SeqTwoByteStringSize(Map* map) {
uint32_t length = READ_INT_FIELD(this, kLengthOffset);
+ ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
+ ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
+ ASSERT(kLongStringTag == 0);
+
// Use the map (and not 'this') to compute the size tag, since
// TwoByteStringSize is called during GC when maps are encoded.
- switch (map_size_tag(map)) {
- case kShortStringTag:
- length = length >> kShortLengthShift;
- break;
- case kMediumStringTag:
- length = length >> kMediumLengthShift;
- break;
- case kLongStringTag:
- length = length >> kLongLengthShift;
- break;
- default:
- break;
- }
+ length >>= map_size_tag(map) + kLongLengthShift;
+
return SizeFor(length);
}
int SeqAsciiString::SeqAsciiStringSize(Map* map) {
uint32_t length = READ_INT_FIELD(this, kLengthOffset);
+ ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
+ ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
+ ASSERT(kLongStringTag == 0);
+
// Use the map (and not 'this') to compute the size tag, since
// AsciiStringSize is called during GC when maps are encoded.
- switch (map_size_tag(map)) {
- case kShortStringTag:
- length = length >> kShortLengthShift;
- break;
- case kMediumStringTag:
- length = length >> kMediumLengthShift;
- break;
- case kLongStringTag:
- length = length >> kLongLengthShift;
- break;
- default:
- break;
- }
+ length >>= map_size_tag(map) + kLongLengthShift;
return SizeFor(length);
}
} else {
payload = v8::internal::HashField(GetHash(), false);
}
- return (payload & 0x00FFFFFF) | (length_ << String::kShortLengthShift);
+ return (payload & ((1 << String::kShortLengthShift) - 1)) |
+ (length_ << String::kShortLengthShift);
} else if (length_ <= String::kMaxMediumStringSize) {
uint32_t payload = v8::internal::HashField(GetHash(), false);
- return (payload & 0x0000FFFF) | (length_ << String::kMediumLengthShift);
+ return (payload & ((1 << String::kMediumLengthShift) - 1)) |
+ (length_ << String::kMediumLengthShift);
} else {
return v8::internal::HashField(length_, false);
}
const uint32_t kStringTag = 0x0;
const uint32_t kNotStringTag = 0x80;
-// If bit 7 is clear, bits 5 and 6 are the string's size (short, medium, or
-// long).
-const uint32_t kStringSizeMask = 0x60;
-const uint32_t kShortStringTag = 0x0;
-const uint32_t kMediumStringTag = 0x20;
-const uint32_t kLongStringTag = 0x40;
-
-// If bit 7 is clear, bit 4 indicates that the string is a symbol (if set) or
+// If bit 7 is clear, bit 5 indicates that the string is a symbol (if set) or
// not (if cleared).
-const uint32_t kIsSymbolMask = 0x10;
+const uint32_t kIsSymbolMask = 0x20;
const uint32_t kNotSymbolTag = 0x0;
-const uint32_t kSymbolTag = 0x10;
-
-// If bit 7 is clear, and the string representation is a sequential string,
-// then bit 3 indicates whether the string consists of two-byte characters or
-// one-byte characters.
-const uint32_t kStringEncodingMask = 0x8;
+const uint32_t kSymbolTag = 0x20;
+
+// If bit 7 is clear, bits 3 and 4 are the string's size (short, medium or
+// long). These values are very special in that they are also used to shift
+// the length field to get the length, removing the hash value. This avoids
+// using if or switch when getting the length of a string.
+const uint32_t kStringSizeMask = 0x18;
+const uint32_t kShortStringTag = 0x18;
+const uint32_t kMediumStringTag = 0x10;
+const uint32_t kLongStringTag = 0x00;
+
+// If bit 7 is clear then bit 2 indicates whether the string consists of
+// two-byte characters or one-byte characters.
+const uint32_t kStringEncodingMask = 0x4;
const uint32_t kTwoByteStringTag = 0x0;
-const uint32_t kAsciiStringTag = 0x8;
+const uint32_t kAsciiStringTag = 0x4;
-// If bit 7 is clear, the low-order 3 bits indicate the representation
+// If bit 7 is clear, the low-order 2 bits indicate the representation
// of the string.
-const uint32_t kStringRepresentationMask = 0x07;
+const uint32_t kStringRepresentationMask = 0x03;
enum StringRepresentationTag {
kSeqStringTag = 0x0,
kConsStringTag = 0x1,
static const int kSize = kLengthOffset + kIntSize;
// Limits on sizes of different types of strings.
- static const int kMaxShortStringSize = 255;
- static const int kMaxMediumStringSize = 65535;
+ static const int kMaxShortStringSize = 63;
+ static const int kMaxMediumStringSize = 16383;
static const int kMaxArrayIndexSize = 10;
// Array index strings this short can keep their index in the hash
// field.
- static const int kMaxCachedArrayIndexLength = 6;
+ static const int kMaxCachedArrayIndexLength = 7;
// Shift constants for retriving length and hash code from
// length/hash field.
static const int kHashShift = kNofLengthBitFields;
- static const int kShortLengthShift = 3 * kBitsPerByte;
- static const int kMediumLengthShift = 2 * kBitsPerByte;
- static const int kLongLengthShift = kHashShift;
+ static const int kShortLengthShift = kHashShift + kShortStringTag;
+ static const int kMediumLengthShift = kHashShift + kMediumStringTag;
+ static const int kLongLengthShift = kHashShift + kLongStringTag;
// Limit for truncation in short printing.
static const int kMaxShortPrintLength = 1024;
}
-void StubCompiler::GenerateLoadShortStringLength(MacroAssembler* masm,
- Register receiver,
- Register scratch,
- Label* miss_label) {
+void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
+ Register receiver,
+ Register scratch,
+ Label* miss_label) {
// Check that the receiver isn't a smi.
__ test(receiver, Immediate(kSmiTagMask));
__ j(zero, miss_label, not_taken);
- // Check that the object is a short string.
+ // Check that the object is a string.
__ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
__ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
- __ and_(scratch, kIsNotStringMask | kStringSizeMask);
- __ cmp(scratch, kStringTag | kShortStringTag);
- __ j(not_equal, miss_label, not_taken);
-
- // Load length directly from the string.
- __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
- __ shr(eax, String::kShortLengthShift);
- __ shl(eax, kSmiTagSize);
- __ ret(0);
-}
-
-void StubCompiler::GenerateLoadMediumStringLength(MacroAssembler* masm,
- Register receiver,
- Register scratch,
- Label* miss_label) {
- // Check that the receiver isn't a smi.
- __ test(receiver, Immediate(kSmiTagMask));
- __ j(zero, miss_label, not_taken);
+ ASSERT(kNotStringTag != 0);
+ __ test(scratch, Immediate(kNotStringTag));
+ __ j(not_zero, miss_label, not_taken);
- // Check that the object is a short string.
- __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
- __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
- __ and_(scratch, kIsNotStringMask | kStringSizeMask);
- __ cmp(scratch, kStringTag | kMediumStringTag);
- __ j(not_equal, miss_label, not_taken);
+ __ and_(scratch, kStringSizeMask);
// Load length directly from the string.
__ mov(eax, FieldOperand(receiver, String::kLengthOffset));
- __ shr(eax, String::kMediumLengthShift);
- __ shl(eax, kSmiTagSize);
- __ ret(0);
-}
-
-void StubCompiler::GenerateLoadLongStringLength(MacroAssembler* masm,
- Register receiver,
- Register scratch,
- Label* miss_label) {
- // Check that the receiver isn't a smi.
- __ test(receiver, Immediate(kSmiTagMask));
- __ j(zero, miss_label, not_taken);
-
- // Check that the object is a short string.
- __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
- __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
- __ and_(scratch, kIsNotStringMask | kStringSizeMask);
- __ cmp(scratch, kStringTag | kLongStringTag);
- __ j(not_equal, miss_label, not_taken);
-
- // Load length directly from the string.
- __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
- __ shr(eax, String::kLongLengthShift);
+ // ecx is also the receiver.
+ __ lea(ecx, Operand(scratch, String::kLongLengthShift));
+ __ shr(eax); // ecx is implicit shift register.
__ shl(eax, kSmiTagSize);
__ ret(0);
}
}
-Object* KeyedLoadStubCompiler::CompileLoadShortStringLength(String* name) {
- // ----------- S t a t e -------------
- // -- esp[0] : return address
- // -- esp[4] : name
- // -- esp[8] : receiver
- // -----------------------------------
- HandleScope scope;
- Label miss;
-
- __ mov(eax, (Operand(esp, kPointerSize)));
- __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
- __ IncrementCounter(&Counters::keyed_load_string_length, 1);
-
- // Check that the name has not changed.
- __ cmp(Operand(eax), Immediate(Handle<String>(name)));
- __ j(not_equal, &miss, not_taken);
-
- GenerateLoadShortStringLength(masm(), ecx, edx, &miss);
- __ bind(&miss);
- __ DecrementCounter(&Counters::keyed_load_string_length, 1);
- GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
-
- // Return the generated code.
- return GetCode(CALLBACKS);
-}
-
-
-Object* KeyedLoadStubCompiler::CompileLoadMediumStringLength(String* name) {
- // ----------- S t a t e -------------
- // -- esp[0] : return address
- // -- esp[4] : name
- // -- esp[8] : receiver
- // -----------------------------------
- HandleScope scope;
- Label miss;
-
- __ mov(eax, (Operand(esp, kPointerSize)));
- __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
- __ IncrementCounter(&Counters::keyed_load_string_length, 1);
-
- // Check that the name has not changed.
- __ cmp(Operand(eax), Immediate(Handle<String>(name)));
- __ j(not_equal, &miss, not_taken);
-
- GenerateLoadMediumStringLength(masm(), ecx, edx, &miss);
- __ bind(&miss);
- __ DecrementCounter(&Counters::keyed_load_string_length, 1);
- GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
-
- // Return the generated code.
- return GetCode(CALLBACKS);
-}
-
-
-Object* KeyedLoadStubCompiler::CompileLoadLongStringLength(String* name) {
+Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
// ----------- S t a t e -------------
// -- esp[0] : return address
// -- esp[4] : name
__ cmp(Operand(eax), Immediate(Handle<String>(name)));
__ j(not_equal, &miss, not_taken);
- GenerateLoadLongStringLength(masm(), ecx, edx, &miss);
+ GenerateLoadStringLength(masm(), ecx, edx, &miss);
__ bind(&miss);
__ DecrementCounter(&Counters::keyed_load_string_length, 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
}
-Object* StubCache::ComputeKeyedLoadShortStringLength(String* name,
- String* receiver) {
+Object* StubCache::ComputeKeyedLoadStringLength(String* name,
+ String* receiver) {
Code::Flags flags =
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Object* code = receiver->map()->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
KeyedLoadStubCompiler compiler;
- code = compiler.CompileLoadShortStringLength(name);
- if (code->IsFailure()) return code;
- LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
- Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
- if (result->IsFailure()) return result;
- }
- return code;
-}
-
-
-Object* StubCache::ComputeKeyedLoadMediumStringLength(String* name,
- String* receiver) {
- Code::Flags flags =
- Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
- Object* code = receiver->map()->FindInCodeCache(name, flags);
- if (code->IsUndefined()) {
- KeyedLoadStubCompiler compiler;
- code = compiler.CompileLoadMediumStringLength(name);
- if (code->IsFailure()) return code;
- LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
- Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
- if (result->IsFailure()) return result;
- }
- return code;
-}
-
-
-Object* StubCache::ComputeKeyedLoadLongStringLength(String* name,
- String* receiver) {
- Code::Flags flags =
- Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
- Object* code = receiver->map()->FindInCodeCache(name, flags);
- if (code->IsUndefined()) {
- KeyedLoadStubCompiler compiler;
- code = compiler.CompileLoadLongStringLength(name);
+ code = compiler.CompileLoadStringLength(name);
if (code->IsFailure()) return code;
LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
static Object* ComputeKeyedLoadArrayLength(String* name, JSArray* receiver);
- static Object* ComputeKeyedLoadShortStringLength(String* name,
- String* receiver);
-
- static Object* ComputeKeyedLoadMediumStringLength(String* name,
- String* receiver);
-
- static Object* ComputeKeyedLoadLongStringLength(String* name,
- String* receiver);
+ static Object* ComputeKeyedLoadStringLength(String* name,
+ String* receiver);
static Object* ComputeKeyedLoadFunctionPrototype(String* name,
JSFunction* receiver);
Register receiver,
Register scratch,
Label* miss_label);
- static void GenerateLoadShortStringLength(MacroAssembler* masm,
- Register receiver,
- Register scratch,
- Label* miss_label);
- static void GenerateLoadMediumStringLength(MacroAssembler* masm,
- Register receiver,
- Register scratch,
- Label* miss_label);
- static void GenerateLoadLongStringLength(MacroAssembler* masm,
- Register receiver,
- Register scratch,
- Label* miss_label);
+ static void GenerateLoadStringLength(MacroAssembler* masm,
+ Register receiver,
+ Register scratch,
+ Label* miss_label);
static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
Register receiver,
Register scratch1,
JSObject* holder,
String* name);
Object* CompileLoadArrayLength(String* name);
- Object* CompileLoadShortStringLength(String* name);
- Object* CompileLoadMediumStringLength(String* name);
- Object* CompileLoadLongStringLength(String* name);
+ Object* CompileLoadStringLength(String* name);
Object* CompileLoadFunctionPrototype(String* name);
private: