}
-void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
- Label* miss,
- Label* done,
- Register receiver,
- Register properties,
- Handle<String> name,
- Register scratch0) {
+void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
+ Label* miss,
+ Label* done,
+ Register receiver,
+ Register properties,
+ Handle<Name> name,
+ Register scratch0) {
+ ASSERT(name->IsUniqueName());
// If names of slots in range from 1 to kProbes - 1 for the hash value are
// not equal to the name and kProbes-th slot is not used (its name is the
// undefined value), it guarantees the hash table doesn't contain the
__ ldr(index, FieldMemOperand(properties, kCapacityOffset));
__ sub(index, index, Operand(1));
__ and_(index, index, Operand(
- Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i))));
+ Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i))));
// Scale the index by multiplying by the entry size.
- ASSERT(StringDictionary::kEntrySize == 3);
+ ASSERT(NameDictionary::kEntrySize == 3);
__ add(index, index, Operand(index, LSL, 1)); // index *= 3.
Register entity_name = scratch0;
__ LoadRoot(tmp, Heap::kTheHoleValueRootIndex);
// Stop if found the property.
- __ cmp(entity_name, Operand(Handle<String>(name)));
+ __ cmp(entity_name, Operand(Handle<Name>(name)));
__ b(eq, miss);
- Label the_hole;
+ Label good;
__ cmp(entity_name, tmp);
- __ b(eq, &the_hole);
+ __ b(eq, &good);
- // Check if the entry name is not an internalized string.
+ // Check if the entry name is not a unique name.
__ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
__ ldrb(entity_name,
FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
__ tst(entity_name, Operand(kIsInternalizedMask));
- __ b(eq, miss);
+ __ b(ne, &good);
+ __ cmp(entity_name, Operand(SYMBOL_TYPE));
+ __ b(ne, miss);
- __ bind(&the_hole);
+ __ bind(&good);
// Restore the properties.
__ ldr(properties,
__ stm(db_w, sp, spill_mask);
__ ldr(r0, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
- __ mov(r1, Operand(Handle<String>(name)));
- StringDictionaryLookupStub stub(NEGATIVE_LOOKUP);
+ __ mov(r1, Operand(Handle<Name>(name)));
+ NameDictionaryLookupStub stub(NEGATIVE_LOOKUP);
__ CallStub(&stub);
__ cmp(r0, Operand::Zero());
__ ldm(ia_w, sp, spill_mask);
}
-// Probe the string dictionary in the |elements| register. Jump to the
+// Probe the name dictionary in the |elements| register. Jump to the
// |done| label if a property with the given name is found. Jump to
// the |miss| label otherwise.
// If lookup was successful |scratch2| will be equal to elements + 4 * index.
-void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
- Label* miss,
- Label* done,
- Register elements,
- Register name,
- Register scratch1,
- Register scratch2) {
+void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
+ Label* miss,
+ Label* done,
+ Register elements,
+ Register name,
+ Register scratch1,
+ Register scratch2) {
ASSERT(!elements.is(scratch1));
ASSERT(!elements.is(scratch2));
ASSERT(!name.is(scratch1));
ASSERT(!name.is(scratch2));
- __ AssertString(name);
+ __ AssertName(name);
// Compute the capacity mask.
__ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset));
// cover ~93% of loads from dictionaries.
for (int i = 0; i < kInlinedProbes; i++) {
// Compute the masked index: (hash + i + i * i) & mask.
- __ ldr(scratch2, FieldMemOperand(name, String::kHashFieldOffset));
+ __ ldr(scratch2, FieldMemOperand(name, Name::kHashFieldOffset));
if (i > 0) {
// Add the probe offset (i + i * i) left shifted to avoid right shifting
// the hash in a separate instruction. The value hash + i + i * i is right
// shifted in the following and instruction.
- ASSERT(StringDictionary::GetProbeOffset(i) <
- 1 << (32 - String::kHashFieldOffset));
+ ASSERT(NameDictionary::GetProbeOffset(i) <
+ 1 << (32 - Name::kHashFieldOffset));
__ add(scratch2, scratch2, Operand(
- StringDictionary::GetProbeOffset(i) << String::kHashShift));
+ NameDictionary::GetProbeOffset(i) << Name::kHashShift));
}
- __ and_(scratch2, scratch1, Operand(scratch2, LSR, String::kHashShift));
+ __ and_(scratch2, scratch1, Operand(scratch2, LSR, Name::kHashShift));
// Scale the index by multiplying by the element size.
- ASSERT(StringDictionary::kEntrySize == 3);
+ ASSERT(NameDictionary::kEntrySize == 3);
// scratch2 = scratch2 * 3.
__ add(scratch2, scratch2, Operand(scratch2, LSL, 1));
__ Move(r0, elements);
__ Move(r1, name);
}
- StringDictionaryLookupStub stub(POSITIVE_LOOKUP);
+ NameDictionaryLookupStub stub(POSITIVE_LOOKUP);
__ CallStub(&stub);
__ cmp(r0, Operand::Zero());
__ mov(scratch2, Operand(r2));
}
-void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
+void NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
// This stub overrides SometimesSetsUpAFrame() to return false. That means
// we cannot call anything that could cause a GC from this stub.
// Registers:
- // result: StringDictionary to probe
+ // result: NameDictionary to probe
// r1: key
- // : StringDictionary to probe.
- // index_: will hold an index of entry if lookup is successful.
- // might alias with result_.
+ // dictionary: NameDictionary to probe.
+ // index: will hold an index of entry if lookup is successful.
+ // might alias with result_.
// Returns:
// result_ is zero if lookup failed, non zero otherwise.
__ mov(mask, Operand(mask, ASR, kSmiTagSize));
__ sub(mask, mask, Operand(1));
- __ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset));
+ __ ldr(hash, FieldMemOperand(key, Name::kHashFieldOffset));
__ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
// Add the probe offset (i + i * i) left shifted to avoid right shifting
// the hash in a separate instruction. The value hash + i + i * i is right
// shifted in the following and instruction.
- ASSERT(StringDictionary::GetProbeOffset(i) <
- 1 << (32 - String::kHashFieldOffset));
+ ASSERT(NameDictionary::GetProbeOffset(i) <
+ 1 << (32 - Name::kHashFieldOffset));
__ add(index, hash, Operand(
- StringDictionary::GetProbeOffset(i) << String::kHashShift));
+ NameDictionary::GetProbeOffset(i) << Name::kHashShift));
} else {
__ mov(index, Operand(hash));
}
- __ and_(index, mask, Operand(index, LSR, String::kHashShift));
+ __ and_(index, mask, Operand(index, LSR, Name::kHashShift));
// Scale the index by multiplying by the entry size.
- ASSERT(StringDictionary::kEntrySize == 3);
+ ASSERT(NameDictionary::kEntrySize == 3);
__ add(index, index, Operand(index, LSL, 1)); // index *= 3.
ASSERT_EQ(kSmiTagSize, 1);
__ b(eq, &in_dictionary);
if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
- // Check if the entry name is not an internalized string.
+ // Check if the entry name is not a unique name.
+ Label cont;
__ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
__ ldrb(entry_key,
FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
__ tst(entry_key, Operand(kIsInternalizedMask));
- __ b(eq, &maybe_in_dictionary);
+ __ b(ne, &cont);
+ __ cmp(entry_key, Operand(SYMBOL_TYPE));
+ __ b(ne, &maybe_in_dictionary);
+ __ bind(&cont);
}
}
};
-class StringDictionaryLookupStub: public PlatformCodeStub {
+class NameDictionaryLookupStub: public PlatformCodeStub {
public:
enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
- explicit StringDictionaryLookupStub(LookupMode mode) : mode_(mode) { }
+ explicit NameDictionaryLookupStub(LookupMode mode) : mode_(mode) { }
void Generate(MacroAssembler* masm);
Label* done,
Register receiver,
Register properties,
- Handle<String> name,
+ Handle<Name> name,
Register scratch0);
static void GeneratePositiveLookup(MacroAssembler* masm,
static const int kTotalProbes = 20;
static const int kCapacityOffset =
- StringDictionary::kHeaderSize +
- StringDictionary::kCapacityIndex * kPointerSize;
+ NameDictionary::kHeaderSize +
+ NameDictionary::kCapacityIndex * kPointerSize;
static const int kElementsStartOffset =
- StringDictionary::kHeaderSize +
- StringDictionary::kElementsStartIndex * kPointerSize;
+ NameDictionary::kHeaderSize +
+ NameDictionary::kElementsStartIndex * kPointerSize;
- Major MajorKey() { return StringDictionaryLookup; }
+ Major MajorKey() { return NameDictionaryLookup; }
int MinorKey() {
return LookupModeBits::encode(mode_);
// Generated code falls through if the receiver is a regular non-global
// JS object with slow properties and no interceptors.
-static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
- Register receiver,
- Register elements,
- Register t0,
- Register t1,
- Label* miss) {
+static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm,
+ Register receiver,
+ Register elements,
+ Register t0,
+ Register t1,
+ Label* miss) {
// Register usage:
// receiver: holds the receiver on entry and is unchanged.
// elements: holds the property dictionary on fall through.
Label done;
// Probe the dictionary.
- StringDictionaryLookupStub::GeneratePositiveLookup(masm,
- miss,
- &done,
- elements,
- name,
- scratch1,
- scratch2);
+ NameDictionaryLookupStub::GeneratePositiveLookup(masm,
+ miss,
+ &done,
+ elements,
+ name,
+ scratch1,
+ scratch2);
// If probing finds an entry check that the value is a normal
// property.
__ bind(&done); // scratch2 == elements + 4 * index
- const int kElementsStartOffset = StringDictionary::kHeaderSize +
- StringDictionary::kElementsStartIndex * kPointerSize;
+ const int kElementsStartOffset = NameDictionary::kHeaderSize +
+ NameDictionary::kElementsStartIndex * kPointerSize;
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
__ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
__ tst(scratch1, Operand(PropertyDetails::TypeField::kMask << kSmiTagSize));
Label done;
// Probe the dictionary.
- StringDictionaryLookupStub::GeneratePositiveLookup(masm,
- miss,
- &done,
- elements,
- name,
- scratch1,
- scratch2);
+ NameDictionaryLookupStub::GeneratePositiveLookup(masm,
+ miss,
+ &done,
+ elements,
+ name,
+ scratch1,
+ scratch2);
// If probing finds an entry in the dictionary check that the value
// is a normal property that is not read only.
__ bind(&done); // scratch2 == elements + 4 * index
- const int kElementsStartOffset = StringDictionary::kHeaderSize +
- StringDictionary::kElementsStartIndex * kPointerSize;
+ const int kElementsStartOffset = NameDictionary::kHeaderSize +
+ NameDictionary::kElementsStartIndex * kPointerSize;
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
const int kTypeAndReadOnlyMask =
(PropertyDetails::TypeField::kMask |
}
-// Checks whether a key is an array index string or an internalized string.
-// Falls through if a key is an internalized string.
-static void GenerateKeyStringCheck(MacroAssembler* masm,
- Register key,
- Register map,
- Register hash,
- Label* index_string,
- Label* not_internalized) {
+// Checks whether a key is an array index string or a unique name.
+// Falls through if a key is a unique name.
+static void GenerateKeyNameCheck(MacroAssembler* masm,
+ Register key,
+ Register map,
+ Register hash,
+ Label* index_string,
+ Label* not_unique) {
// The key is not a smi.
- // Is it a string?
- __ CompareObjectType(key, map, hash, FIRST_NONSTRING_TYPE);
- __ b(ge, not_internalized);
+ Label unique;
+ // Is it a name?
+ __ CompareObjectType(key, map, hash, LAST_UNIQUE_NAME_TYPE);
+ __ b(hi, not_unique);
+ STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
+ __ b(eq, &unique);
// Is the string an array index, with cached numeric value?
- __ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset));
- __ tst(hash, Operand(String::kContainsCachedArrayIndexMask));
+ __ ldr(hash, FieldMemOperand(key, Name::kHashFieldOffset));
+ __ tst(hash, Operand(Name::kContainsCachedArrayIndexMask));
__ b(eq, index_string);
// Is the string internalized?
__ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset));
STATIC_ASSERT(kInternalizedTag != 0);
__ tst(hash, Operand(kIsInternalizedMask));
- __ b(eq, not_internalized);
+ __ b(eq, not_unique);
+
+ __ bind(&unique);
}
// Get the receiver of the function from the stack into r1.
__ ldr(r1, MemOperand(sp, argc * kPointerSize));
- GenerateStringDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss);
+ GenerateNameDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss);
// r0: elements
// Search the dictionary - put result in register r1.
__ ldr(r1, MemOperand(sp, argc * kPointerSize));
Label do_call, slow_call, slow_load, slow_reload_receiver;
- Label check_number_dictionary, check_string, lookup_monomorphic_cache;
- Label index_smi, index_string;
+ Label check_number_dictionary, check_name, lookup_monomorphic_cache;
+ Label index_smi, index_name;
// Check that the key is a smi.
- __ JumpIfNotSmi(r2, &check_string);
+ __ JumpIfNotSmi(r2, &check_name);
__ bind(&index_smi);
// Now the key is known to be a smi. This place is also jumped to from below
// where a numeric string is converted to a smi.
__ mov(r1, r0);
__ jmp(&do_call);
- __ bind(&check_string);
- GenerateKeyStringCheck(masm, r2, r0, r3, &index_string, &slow_call);
+ __ bind(&check_name);
+ GenerateKeyNameCheck(masm, r2, r0, r3, &index_name, &slow_call);
- // The key is known to be internalized.
+ // The key is known to be a unique name.
// If the receiver is a regular JS object with slow properties then do
// a quick inline probe of the receiver's dictionary.
// Otherwise do the monomorphic cache probe.
__ bind(&slow_call);
// This branch is taken if:
// - the receiver requires boxing or access check,
- // - the key is neither smi nor an internalized string,
+ // - the key is neither smi nor a unique name,
// - the value loaded is not a function,
// - there is hope that the runtime will create a monomorphic call stub
// that will get fetched next time.
__ IncrementCounter(counters->keyed_call_generic_slow(), 1, r0, r3);
GenerateMiss(masm, argc);
- __ bind(&index_string);
+ __ bind(&index_name);
__ IndexFromHash(r3, r2);
// Now jump to the place where smi keys are handled.
__ jmp(&index_smi);
// -- lr : return address
// -----------------------------------
- // Check if the name is a string.
+ // Check if the name is really a name.
Label miss;
__ JumpIfSmi(r2, &miss);
- __ IsObjectJSStringType(r2, r0, &miss);
+ __ IsObjectNameType(r2, r0, &miss);
CallICBase::GenerateNormal(masm, argc);
__ bind(&miss);
// -----------------------------------
Label miss;
- GenerateStringDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss);
+ GenerateNameDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss);
// r1: elements
GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4);
// -- r0 : key
// -- r1 : receiver
// -----------------------------------
- Label slow, check_string, index_smi, index_string, property_array_property;
+ Label slow, check_name, index_smi, index_name, property_array_property;
Label probe_dictionary, check_number_dictionary;
Register key = r0;
Isolate* isolate = masm->isolate();
// Check that the key is a smi.
- __ JumpIfNotSmi(key, &check_string);
+ __ JumpIfNotSmi(key, &check_name);
__ bind(&index_smi);
// Now the key is known to be a smi. This place is also jumped to from below
// where a numeric string is converted to a smi.
1, r2, r3);
GenerateRuntimeGetProperty(masm);
- __ bind(&check_string);
- GenerateKeyStringCheck(masm, key, r2, r3, &index_string, &slow);
+ __ bind(&check_name);
+ GenerateKeyNameCheck(masm, key, r2, r3, &index_name, &slow);
GenerateKeyedLoadReceiverCheck(
masm, receiver, r2, r3, Map::kHasNamedInterceptor, &slow);
__ b(eq, &probe_dictionary);
// Load the map of the receiver, compute the keyed lookup cache hash
- // based on 32 bits of the map pointer and the string hash.
+ // based on 32 bits of the map pointer and the name hash.
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
__ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift));
- __ ldr(r4, FieldMemOperand(r0, String::kHashFieldOffset));
- __ eor(r3, r3, Operand(r4, ASR, String::kHashShift));
+ __ ldr(r4, FieldMemOperand(r0, Name::kHashFieldOffset));
+ __ eor(r3, r3, Operand(r4, ASR, Name::kHashShift));
int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
__ And(r3, r3, Operand(mask));
- // Load the key (consisting of map and internalized string) from the cache and
+ // Load the key (consisting of map and unique name) from the cache and
// check for match.
Label load_in_object_property;
static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
__ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex));
__ cmp(r2, r5);
__ b(ne, &try_next_entry);
- __ ldr(r5, MemOperand(r4, -kPointerSize)); // Load string
+ __ ldr(r5, MemOperand(r4, -kPointerSize)); // Load name
__ cmp(r0, r5);
__ b(eq, &hit_on_nth_entry[i]);
__ bind(&try_next_entry);
}
- // Last entry: Load map and move r4 to string.
+ // Last entry: Load map and move r4 to name.
__ ldr(r5, MemOperand(r4, kPointerSize, PostIndex));
__ cmp(r2, r5);
__ b(ne, &slow);
isolate->counters()->keyed_load_generic_symbol(), 1, r2, r3);
__ Ret();
- __ bind(&index_string);
+ __ bind(&index_name);
__ IndexFromHash(r3, key);
// Now jump to the place where smi keys are handled.
__ jmp(&index_smi);
// -----------------------------------
Label miss;
- GenerateStringDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss);
+ GenerateNameDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss);
GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5);
Counters* counters = masm->isolate()->counters();
}
+void MacroAssembler::IsObjectNameType(Register object,
+ Register scratch,
+ Label* fail) {
+ ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
+ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+ cmp(scratch, Operand(LAST_NAME_TYPE));
+ b(hi, fail);
+}
+
+
#ifdef ENABLE_DEBUGGER_SUPPORT
void MacroAssembler::DebugBreak() {
mov(r0, Operand::Zero());
}
+void MacroAssembler::AssertName(Register object) {
+ if (emit_debug_code()) {
+ STATIC_ASSERT(kSmiTag == 0);
+ tst(object, Operand(kSmiTagMask));
+ Check(ne, "Operand is a smi and not a name");
+ push(object);
+ ldr(object, FieldMemOperand(object, HeapObject::kMapOffset));
+ CompareInstanceType(object, object, LAST_NAME_TYPE);
+ pop(object);
+ Check(le, "Operand is not a name");
+ }
+}
+
+
void MacroAssembler::AssertRootValue(Register src,
Heap::RootListIndex root_value_index,
Register scratch,
Label* fail);
+ void IsObjectNameType(Register object,
+ Register scratch,
+ Label* fail);
+
#ifdef ENABLE_DEBUGGER_SUPPORT
// ---------------------------------------------------------------------------
// Debugger Support
void AssertNotSmi(Register object);
void AssertSmi(Register object);
- // Abort execution if argument is a string, enabled via --debug-code.
+ // Abort execution if argument is not a string, enabled via --debug-code.
void AssertString(Register object);
+ // Abort execution if argument is not a name, enabled via --debug-code.
+ void AssertName(Register object);
+
// Abort execution if argument is not the root value with the given index,
// enabled via --debug-code.
void AssertRootValue(Register src,
// the property. This function may return false negatives, so miss_label
// must always call a backup property check that is complete.
// This function is safe to call if the receiver has fast properties.
-// Name must be internalized and receiver must be a heap object.
+// Name must be unique and receiver must be a heap object.
static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
Label* miss_label,
Register receiver,
- Handle<String> name,
+ Handle<Name> name,
Register scratch0,
Register scratch1) {
- ASSERT(name->IsInternalizedString());
+ ASSERT(name->IsUniqueName());
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
__ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
__ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
- StringDictionaryLookupStub::GenerateNegativeLookup(masm,
- miss_label,
- &done,
- receiver,
- properties,
- name,
- scratch1);
+ NameDictionaryLookupStub::GenerateNegativeLookup(masm,
+ miss_label,
+ &done,
+ receiver,
+ properties,
+ name,
+ scratch1);
__ bind(&done);
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
}
__ JumpIfSmi(receiver, &miss);
// Get the map of the receiver and compute the hash.
- __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset));
+ __ ldr(scratch, FieldMemOperand(name, Name::kHashFieldOffset));
__ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
__ add(scratch, scratch, Operand(ip));
uint32_t mask = kPrimaryTableSize - 1;
Handle<JSObject> object,
int index,
Handle<Map> transition,
- Handle<String> name,
+ Handle<Name> name,
Register receiver_reg,
Register name_reg,
Register scratch1,
void Compile(MacroAssembler* masm,
Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
LookupResult* lookup,
Register receiver,
Register scratch1,
Register scratch3,
Handle<JSObject> interceptor_holder,
LookupResult* lookup,
- Handle<String> name,
+ Handle<Name> name,
const CallOptimization& optimization,
Label* miss_label) {
ASSERT(optimization.is_constant_call());
Register scratch1,
Register scratch2,
Register scratch3,
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> interceptor_holder,
Label* miss_label) {
Register holder =
// property.
static void GenerateCheckPropertyCell(MacroAssembler* masm,
Handle<GlobalObject> global,
- Handle<String> name,
+ Handle<Name> name,
Register scratch,
Label* miss) {
Handle<JSGlobalPropertyCell> cell =
static void GenerateCheckPropertyCells(MacroAssembler* masm,
Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Register scratch,
Label* miss) {
Handle<JSObject> current = object;
Register holder_reg,
Register scratch1,
Register scratch2,
- Handle<String> name,
+ Handle<Name> name,
int save_at_depth,
Label* miss,
PrototypeCheckType check) {
if (!current->HasFastProperties() &&
!current->IsJSGlobalObject() &&
!current->IsJSGlobalProxy()) {
- if (!name->IsInternalizedString()) {
- name = factory()->InternalizeString(name);
+ if (!name->IsUniqueName()) {
+ ASSERT(name->IsString());
+ name = factory()->InternalizeString(Handle<String>::cast(name));
}
ASSERT(current->property_dictionary()->FindEntry(*name) ==
- StringDictionary::kNotFound);
+ NameDictionary::kNotFound);
GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
scratch1, scratch2);
Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Label* success,
Handle<ExecutableAccessorInfo> callback) {
Label miss;
// Probe the dictionary.
Label probe_done;
- StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
- &miss,
- &probe_done,
- dictionary,
- this->name(),
- scratch2(),
- scratch3());
+ NameDictionaryLookupStub::GeneratePositiveLookup(masm(),
+ &miss,
+ &probe_done,
+ dictionary,
+ this->name(),
+ scratch2(),
+ scratch3());
__ bind(&probe_done);
// If probing finds an entry in the dictionary, scratch3 contains the
// pointer into the dictionary. Check that the value is the callback.
Register pointer = scratch3();
- const int kElementsStartOffset = StringDictionary::kHeaderSize +
- StringDictionary::kElementsStartIndex * kPointerSize;
+ const int kElementsStartOffset = NameDictionary::kHeaderSize +
+ NameDictionary::kElementsStartIndex * kPointerSize;
const int kValueOffset = kElementsStartOffset + kPointerSize;
__ ldr(scratch2(), FieldMemOperand(pointer, kValueOffset));
__ cmp(scratch2(), Operand(callback));
void BaseLoadStubCompiler::NonexistentHandlerFrontend(
Handle<JSObject> object,
Handle<JSObject> last,
- Handle<String> name,
+ Handle<Name> name,
Label* success,
Handle<GlobalObject> global) {
Label miss;
__ Push(reg, scratch3());
__ mov(scratch3(), Operand(ExternalReference::isolate_address()));
__ Push(scratch3(), name());
- __ mov(r0, sp); // r0 = Handle<String>
+ __ mov(r0, sp); // r0 = Handle<Name>
const int kApiStackSpace = 1;
FrameScope frame_scope(masm(), StackFrame::MANUAL);
Handle<JSObject> object,
Handle<JSObject> interceptor_holder,
LookupResult* lookup,
- Handle<String> name) {
+ Handle<Name> name) {
ASSERT(interceptor_holder->HasNamedInterceptor());
ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
}
-void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
+void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
if (kind_ == Code::KEYED_CALL_IC) {
__ cmp(r2, Operand(name));
__ b(ne, miss);
void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Label* miss) {
ASSERT(holder->IsGlobalObject());
Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
Handle<JSObject> holder,
PropertyIndex index,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
CheckType check,
Label* success) {
// ----------- S t a t e -------------
Handle<Code> CallStubCompiler::CompileCallConstant(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
CheckType check,
Handle<JSFunction> function) {
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
Handle<JSGlobalPropertyCell>::null(),
- function, name);
+ function, Handle<String>::cast(name));
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
__ bind(&success);
CompileHandlerBackend(function);
-
// Return the generated code.
return GetCode(function);
}
Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
Handle<GlobalObject> holder,
Handle<JSGlobalPropertyCell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
// -----------------------------------
if (HasCustomCallGenerator(function)) {
- Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
+ Handle<Code> code = CompileCustomCall(
+ object, holder, cell, function, Handle<String>::cast(name));
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
int index,
Handle<Map> transition,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : receiver
Handle<Code> StoreStubCompiler::CompileStoreCallback(
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<JSFunction> setter) {
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> receiver,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : receiver
Handle<Code> StoreStubCompiler::CompileStoreGlobal(
Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : receiver
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
Handle<JSObject> object,
Handle<JSObject> last,
- Handle<String> name,
+ Handle<Name> name,
Handle<GlobalObject> global) {
Label success;
}
-void KeyedLoadStubCompiler::GenerateNameCheck(Handle<String> name,
+void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
Register name_reg,
Label* miss) {
__ cmp(name_reg, Operand(name));
Handle<JSObject> object,
Handle<GlobalObject> global,
Handle<JSGlobalPropertyCell> cell,
- Handle<String> name,
+ Handle<Name> name,
bool is_dont_delete) {
Label success, miss;
Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps,
CodeHandleList* handlers,
- Handle<String> name,
+ Handle<Name> name,
Code::StubType type,
IcCheckType check) {
Label miss;
Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
int index,
Handle<Map> transition,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : name
switch (details.type()) {
case FIELD: {
HandleScope inner(isolate());
- Handle<String> key = Handle<String>(descs->GetKey(i));
+ Handle<Name> key = Handle<Name>(descs->GetKey(i));
int index = descs->GetFieldIndex(i);
Handle<Object> value = Handle<Object>(from->FastPropertyAt(index),
isolate());
}
case CONSTANT_FUNCTION: {
HandleScope inner(isolate());
- Handle<String> key = Handle<String>(descs->GetKey(i));
+ Handle<Name> key = Handle<Name>(descs->GetKey(i));
Handle<JSFunction> fun =
Handle<JSFunction>(descs->GetConstantFunction(i));
CHECK_NOT_EMPTY_HANDLE(isolate(),
HandleScope inner(isolate());
ASSERT(!to->HasFastProperties());
// Add to dictionary.
- Handle<String> key = Handle<String>(descs->GetKey(i));
+ Handle<Name> key = Handle<Name>(descs->GetKey(i));
Handle<Object> callbacks(descs->GetCallbacksObject(i), isolate());
PropertyDetails d = PropertyDetails(details.attributes(),
CALLBACKS,
}
}
} else {
- Handle<StringDictionary> properties =
- Handle<StringDictionary>(from->property_dictionary());
+ Handle<NameDictionary> properties =
+ Handle<NameDictionary>(from->property_dictionary());
int capacity = properties->Capacity();
for (int i = 0; i < capacity; i++) {
Object* raw_key(properties->KeyAt(i));
if (properties->IsKey(raw_key)) {
- ASSERT(raw_key->IsString());
+ ASSERT(raw_key->IsName());
// If the property is already there we skip it.
LookupResult result(isolate());
- to->LocalLookup(String::cast(raw_key), &result);
+ to->LocalLookup(Name::cast(raw_key), &result);
if (result.IsFound()) continue;
// Set the property.
- Handle<String> key = Handle<String>(String::cast(raw_key));
+ Handle<Name> key = Handle<Name>(Name::cast(raw_key));
Handle<Object> value = Handle<Object>(properties->ValueAt(i),
isolate());
if (value->IsJSGlobalPropertyCell()) {
V(ArrayNArgumentsConstructor) \
V(KeyedStoreElement) \
V(DebuggerStatement) \
- V(StringDictionaryLookup) \
+ V(NameDictionaryLookup) \
V(ElementsTransitionAndStore) \
V(TransitionElementsKind) \
V(StoreArrayLiteralElement) \
void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag,
const char* prefix,
- String* name,
+ Name* name,
Address start) {
if (FilterOutCodeCreateEvent(tag)) return;
CodeEventsContainer evt_rec;
void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
- String* name,
+ Name* name,
String* resource_name,
int line_number,
Address start,
}
-void CpuProfiler::CallbackEvent(String* name, Address entry_point) {
+void CpuProfiler::CallbackEvent(Name* name, Address entry_point) {
Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, String* name) {
+ Code* code, Name* name) {
Isolate* isolate = Isolate::Current();
isolate->cpu_profiler()->processor_->CodeCreateEvent(
tag,
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
- String* name) {
+ Name* name) {
Isolate* isolate = Isolate::Current();
isolate->cpu_profiler()->processor_->CodeCreateEvent(
tag,
}
-void CpuProfiler::GetterCallbackEvent(String* name, Address entry_point) {
+void CpuProfiler::GetterCallbackEvent(Name* name, Address entry_point) {
Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
Logger::CALLBACK_TAG, "get ", name, entry_point);
}
}
-void CpuProfiler::SetterCallbackEvent(String* name, Address entry_point) {
+void CpuProfiler::SetterCallbackEvent(Name* name, Address entry_point) {
Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
Logger::CALLBACK_TAG, "set ", name, entry_point);
}
// Events adding methods. Called by VM threads.
void CallbackCreateEvent(Logger::LogEventsAndTags tag,
- const char* prefix, String* name,
+ const char* prefix, Name* name,
Address start);
void CodeCreateEvent(Logger::LogEventsAndTags tag,
- String* name,
+ Name* name,
String* resource_name, int line_number,
Address start, unsigned size,
Address shared);
// Must be called via PROFILE macro, otherwise will crash when
// profiling is not enabled.
- static void CallbackEvent(String* name, Address entry_point);
+ static void CallbackEvent(Name* name, Address entry_point);
static void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, const char* comment);
static void CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, String* name);
+ Code* code, Name* name);
static void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
- String* name);
+ Name* name);
static void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
static void CodeMovingGCEvent() {}
static void CodeMoveEvent(Address from, Address to);
static void CodeDeleteEvent(Address from);
- static void GetterCallbackEvent(String* name, Address entry_point);
+ static void GetterCallbackEvent(Name* name, Address entry_point);
static void RegExpCodeCreateEvent(Code* code, String* source);
- static void SetterCallbackEvent(String* name, Address entry_point);
+ static void SetterCallbackEvent(Name* name, Address entry_point);
static void SharedFunctionInfoMoveEvent(Address from, Address to);
static INLINE(bool is_profiling(Isolate* isolate)) {
}
-Handle<StringDictionary> Factory::NewStringDictionary(int at_least_space_for) {
+Handle<NameDictionary> Factory::NewNameDictionary(int at_least_space_for) {
ASSERT(0 <= at_least_space_for);
CALL_HEAP_FUNCTION(isolate(),
- StringDictionary::Allocate(at_least_space_for),
- StringDictionary);
+ NameDictionary::Allocate(at_least_space_for),
+ NameDictionary);
}
Handle<UnseededNumberDictionary> NewUnseededNumberDictionary(
int at_least_space_for);
- Handle<StringDictionary> NewStringDictionary(int at_least_space_for);
+ Handle<NameDictionary> NewNameDictionary(int at_least_space_for);
Handle<ObjectHashSet> NewObjectHashSet(int at_least_space_for);
Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
- Handle<String> key,
+ Handle<Name> key,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode) {
Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
PropertyAttributes* attributes) {
Isolate* isolate = receiver->GetIsolate();
CALL_HEAP_FUNCTION(isolate,
int len = array->length();
for (int i = 0; i < len; i++) {
Object* e = array->get(i);
- if (!(e->IsString() || e->IsNumber())) return false;
+ if (!(e->IsName() || e->IsNumber())) return false;
}
return true;
}
return ReduceFixedArrayTo(storage, enum_size);
} else {
- Handle<StringDictionary> dictionary(object->property_dictionary());
+ Handle<NameDictionary> dictionary(object->property_dictionary());
int length = dictionary->NumberOfElements();
if (length == 0) {
// many properties were added but subsequently deleted.
int next_enumeration = dictionary->NextEnumerationIndex();
if (!object->IsGlobalObject() && next_enumeration > (length * 3) / 2) {
- StringDictionary::DoGenerateNewEnumerationIndices(dictionary);
+ NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
next_enumeration = dictionary->NextEnumerationIndex();
}
case FIELD: {
int index = descs->GetFieldIndex(i);
- String* k = descs->GetKey(i);
+ Name* k = descs->GetKey(i);
if (index < js_obj->map()->inobject_properties()) {
Object* value = js_obj->InObjectPropertyAt(index);
if (k != heap_->hidden_string()) {
}
}
} else {
- StringDictionary* dictionary = js_obj->property_dictionary();
+ NameDictionary* dictionary = js_obj->property_dictionary();
int length = dictionary->Capacity();
for (int i = 0; i < length; ++i) {
Object* k = dictionary->KeyAt(i);
void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
int parent_entry,
- String* reference_name,
+ Name* reference_name,
Object* child_obj,
const char* name_format_string,
int field_offset) {
HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL) {
- HeapGraphEdge::Type type = reference_name->length() > 0 ?
- HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
- const char* name = name_format_string != NULL ?
- collection_->names()->GetFormatted(
- name_format_string,
- *reference_name->ToCString(DISALLOW_NULLS,
- ROBUST_STRING_TRAVERSAL)) :
+ HeapGraphEdge::Type type =
+ reference_name->IsSymbol() || String::cast(reference_name)->length() > 0
+ ? HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
+ const char* name = name_format_string != NULL && reference_name->IsString()
+ ? collection_->names()->GetFormatted(
+ name_format_string,
+ *String::cast(reference_name)->ToCString(
+ DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)) :
collection_->names()->GetName(reference_name);
filler_->SetNamedReference(type,
int field_offset);
void SetPropertyReference(HeapObject* parent_obj,
int parent,
- String* reference_name,
+ Name* reference_name,
Object* child,
const char* name_format_string = NULL,
int field_offset = -1);
CreateFixedStubs();
// Allocate the dictionary of intrinsic function names.
- { MaybeObject* maybe_obj = StringDictionary::Allocate(Runtime::kNumFunctions);
+ { MaybeObject* maybe_obj = NameDictionary::Allocate(Runtime::kNumFunctions);
if (!maybe_obj->ToObject(&obj)) return false;
}
{ MaybeObject* maybe_obj = Runtime::InitializeIntrinsicFunctionNames(this,
obj);
if (!maybe_obj->ToObject(&obj)) return false;
}
- set_intrinsic_function_names(StringDictionary::cast(obj));
+ set_intrinsic_function_names(NameDictionary::cast(obj));
{ MaybeObject* maybe_obj = AllocateInitialNumberStringCache();
if (!maybe_obj->ToObject(&obj)) return false;
static bool HasDuplicates(DescriptorArray* descriptors) {
int count = descriptors->number_of_descriptors();
if (count > 1) {
- String* prev_key = descriptors->GetKey(0);
+ Name* prev_key = descriptors->GetKey(0);
for (int i = 1; i != count; i++) {
- String* current_key = descriptors->GetKey(i);
+ Name* current_key = descriptors->GetKey(i);
if (prev_key == current_key) return true;
prev_key = current_key;
}
int initial_size = map->instance_type() == JS_GLOBAL_OBJECT_TYPE ? 64 : 512;
// Allocate a dictionary object for backing storage.
- StringDictionary* dictionary;
+ NameDictionary* dictionary;
MaybeObject* maybe_dictionary =
- StringDictionary::Allocate(
+ NameDictionary::Allocate(
map->NumberOfOwnDescriptors() * 2 + initial_size);
if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
}
-int KeyedLookupCache::Hash(Map* map, String* name) {
+int KeyedLookupCache::Hash(Map* map, Name* name) {
// Uses only lower 32 bits if pointers are larger.
uintptr_t addr_hash =
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map)) >> kMapHashShift;
}
-int KeyedLookupCache::Lookup(Map* map, String* name) {
+int KeyedLookupCache::Lookup(Map* map, Name* name) {
int index = (Hash(map, name) & kHashMask);
for (int i = 0; i < kEntriesPerBucket; i++) {
Key& key = keys_[index + i];
}
-void KeyedLookupCache::Update(Map* map, String* name, int field_offset) {
- String* internalized_name;
- if (HEAP->InternalizeStringIfExists(name, &internalized_name)) {
- int index = (Hash(map, internalized_name) & kHashMask);
- // After a GC there will be free slots, so we use them in order (this may
- // help to get the most frequently used one in position 0).
- for (int i = 0; i< kEntriesPerBucket; i++) {
- Key& key = keys_[index];
- Object* free_entry_indicator = NULL;
- if (key.map == free_entry_indicator) {
- key.map = map;
- key.name = internalized_name;
- field_offsets_[index + i] = field_offset;
- return;
- }
- }
- // No free entry found in this bucket, so we move them all down one and
- // put the new entry at position zero.
- for (int i = kEntriesPerBucket - 1; i > 0; i--) {
- Key& key = keys_[index + i];
- Key& key2 = keys_[index + i - 1];
- key = key2;
- field_offsets_[index + i] = field_offsets_[index + i - 1];
+void KeyedLookupCache::Update(Map* map, Name* name, int field_offset) {
+ if (!name->IsUniqueName()) {
+ String* internalized_string;
+ if (!HEAP->InternalizeStringIfExists(
+ String::cast(name), &internalized_string)) {
+ return;
}
+ name = internalized_string;
+ }
- // Write the new first entry.
+ int index = (Hash(map, name) & kHashMask);
+ // After a GC there will be free slots, so we use them in order (this may
+ // help to get the most frequently used one in position 0).
+ for (int i = 0; i< kEntriesPerBucket; i++) {
Key& key = keys_[index];
- key.map = map;
- key.name = internalized_name;
- field_offsets_[index] = field_offset;
+ Object* free_entry_indicator = NULL;
+ if (key.map == free_entry_indicator) {
+ key.map = map;
+ key.name = name;
+ field_offsets_[index + i] = field_offset;
+ return;
+ }
}
+ // No free entry found in this bucket, so we move them all down one and
+ // put the new entry at position zero.
+ for (int i = kEntriesPerBucket - 1; i > 0; i--) {
+ Key& key = keys_[index + i];
+ Key& key2 = keys_[index + i - 1];
+ key = key2;
+ field_offsets_[index + i] = field_offsets_[index + i - 1];
+ }
+
+ // Write the new first entry.
+ Key& key = keys_[index];
+ key.map = map;
+ key.name = name;
+ field_offsets_[index] = field_offset;
}
V(Object, last_script_id, LastScriptId) \
V(Script, empty_script, EmptyScript) \
V(Smi, real_stack_limit, RealStackLimit) \
- V(StringDictionary, intrinsic_function_names, IntrinsicFunctionNames) \
+ V(NameDictionary, intrinsic_function_names, IntrinsicFunctionNames) \
V(Smi, arguments_adaptor_deopt_pc_offset, ArgumentsAdaptorDeoptPCOffset) \
V(Smi, construct_stub_deopt_pc_offset, ConstructStubDeoptPCOffset) \
V(Smi, getter_stub_deopt_pc_offset, GetterStubDeoptPCOffset) \
class KeyedLookupCache {
public:
// Lookup field offset for (map, name). If absent, -1 is returned.
- int Lookup(Map* map, String* name);
+ int Lookup(Map* map, Name* name);
// Update an element in the cache.
- void Update(Map* map, String* name, int field_offset);
+ void Update(Map* map, Name* name, int field_offset);
// Clear the cache.
void Clear();
}
}
- static inline int Hash(Map* map, String* name);
+ static inline int Hash(Map* map, Name* name);
// Get the address of the keys and field_offsets arrays. Used in
// generated code to perform cache lookups.
struct Key {
Map* map;
- String* name;
+ Name* name;
};
Key keys_[kLength];
public:
// Lookup descriptor index for (map, name).
// If absent, kAbsent is returned.
- int Lookup(Map* source, String* name) {
- if (!StringShape(name).IsInternalized()) return kAbsent;
+ int Lookup(Map* source, Name* name) {
+ if (!name->IsUniqueName()) return kAbsent;
int index = Hash(source, name);
Key& key = keys_[index];
if ((key.source == source) && (key.name == name)) return results_[index];
}
// Update an element in the cache.
- void Update(Map* source, String* name, int result) {
+ void Update(Map* source, Name* name, int result) {
ASSERT(result != kAbsent);
- if (StringShape(name).IsInternalized()) {
+ if (name->IsUniqueName()) {
int index = Hash(source, name);
Key& key = keys_[index];
key.source = source;
}
}
- static int Hash(Object* source, String* name) {
+ static int Hash(Object* source, Name* name) {
// Uses only lower 32 bits if pointers are larger.
uint32_t source_hash =
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(source))
static const int kLength = 64;
struct Key {
Map* source;
- String* name;
+ Name* name;
};
Key keys_[kLength];
// the property. This function may return false negatives, so miss_label
// must always call a backup property check that is complete.
// This function is safe to call if the receiver has fast properties.
-// Name must be an internalized string and receiver must be a heap object.
-void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
- Label* miss,
- Label* done,
- Register properties,
- Handle<String> name,
- Register r0) {
- ASSERT(name->IsInternalizedString());
+// Name must be a unique name and receiver must be a heap object.
+void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
+ Label* miss,
+ Label* done,
+ Register properties,
+ Handle<Name> name,
+ Register r0) {
+ ASSERT(name->IsUniqueName());
// If names of slots in range from 1 to kProbes - 1 for the hash value are
// not equal to the name and kProbes-th slot is not used (its name is the
__ dec(index);
__ and_(index,
Immediate(Smi::FromInt(name->Hash() +
- StringDictionary::GetProbeOffset(i))));
+ NameDictionary::GetProbeOffset(i))));
// Scale the index by multiplying by the entry size.
- ASSERT(StringDictionary::kEntrySize == 3);
+ ASSERT(NameDictionary::kEntrySize == 3);
__ lea(index, Operand(index, index, times_2, 0)); // index *= 3.
Register entity_name = r0;
// Having undefined at this place means the name is not contained.
__ j(equal, done);
// Stop if found the property.
- __ cmp(entity_name, Handle<String>(name));
+ __ cmp(entity_name, Handle<Name>(name));
__ j(equal, miss);
- Label the_hole;
+ Label good;
// Check for the hole and skip.
__ cmp(entity_name, masm->isolate()->factory()->the_hole_value());
- __ j(equal, &the_hole, Label::kNear);
+ __ j(equal, &good, Label::kNear);
- // Check if the entry name is not an internalized string.
+ // Check if the entry name is not a unique name.
__ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
__ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset),
kIsInternalizedMask);
- __ j(zero, miss);
- __ bind(&the_hole);
+ __ j(not_zero, &good);
+ __ cmpb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
+ static_cast<int8_t>(SYMBOL_TYPE));
+ __ j(not_equal, miss);
+ __ bind(&good);
}
- StringDictionaryLookupStub stub(properties,
- r0,
- r0,
- StringDictionaryLookupStub::NEGATIVE_LOOKUP);
+ NameDictionaryLookupStub stub(properties, r0, r0, NEGATIVE_LOOKUP);
__ push(Immediate(Handle<Object>(name)));
__ push(Immediate(name->Hash()));
__ CallStub(&stub);
}
-// Probe the string dictionary in the |elements| register. Jump to the
+// Probe the name dictionary in the |elements| register. Jump to the
// |done| label if a property with the given name is found leaving the
// index into the dictionary in |r0|. Jump to the |miss| label
// otherwise.
-void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
- Label* miss,
- Label* done,
- Register elements,
- Register name,
- Register r0,
- Register r1) {
+void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
+ Label* miss,
+ Label* done,
+ Register elements,
+ Register name,
+ Register r0,
+ Register r1) {
ASSERT(!elements.is(r0));
ASSERT(!elements.is(r1));
ASSERT(!name.is(r0));
ASSERT(!name.is(r1));
- __ AssertString(name);
+ __ AssertName(name);
__ mov(r1, FieldOperand(elements, kCapacityOffset));
__ shr(r1, kSmiTagSize); // convert smi to int
// cover ~93% of loads from dictionaries.
for (int i = 0; i < kInlinedProbes; i++) {
// Compute the masked index: (hash + i + i * i) & mask.
- __ mov(r0, FieldOperand(name, String::kHashFieldOffset));
- __ shr(r0, String::kHashShift);
+ __ mov(r0, FieldOperand(name, Name::kHashFieldOffset));
+ __ shr(r0, Name::kHashShift);
if (i > 0) {
- __ add(r0, Immediate(StringDictionary::GetProbeOffset(i)));
+ __ add(r0, Immediate(NameDictionary::GetProbeOffset(i)));
}
__ and_(r0, r1);
// Scale the index by multiplying by the entry size.
- ASSERT(StringDictionary::kEntrySize == 3);
+ ASSERT(NameDictionary::kEntrySize == 3);
__ lea(r0, Operand(r0, r0, times_2, 0)); // r0 = r0 * 3
// Check if the key is identical to the name.
__ j(equal, done);
}
- StringDictionaryLookupStub stub(elements,
- r1,
- r0,
- POSITIVE_LOOKUP);
+ NameDictionaryLookupStub stub(elements, r1, r0, POSITIVE_LOOKUP);
__ push(name);
- __ mov(r0, FieldOperand(name, String::kHashFieldOffset));
- __ shr(r0, String::kHashShift);
+ __ mov(r0, FieldOperand(name, Name::kHashFieldOffset));
+ __ shr(r0, Name::kHashShift);
__ push(r0);
__ CallStub(&stub);
}
-void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
+void NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
// This stub overrides SometimesSetsUpAFrame() to return false. That means
// we cannot call anything that could cause a GC from this stub.
// Stack frame on entry:
// esp[1 * kPointerSize]: key's hash.
// esp[2 * kPointerSize]: key.
// Registers:
- // dictionary_: StringDictionary to probe.
+ // dictionary_: NameDictionary to probe.
// result_: used as scratch.
// index_: will hold an index of entry if lookup is successful.
// might alias with result_.
// Compute the masked index: (hash + i + i * i) & mask.
__ mov(scratch, Operand(esp, 2 * kPointerSize));
if (i > 0) {
- __ add(scratch, Immediate(StringDictionary::GetProbeOffset(i)));
+ __ add(scratch, Immediate(NameDictionary::GetProbeOffset(i)));
}
__ and_(scratch, Operand(esp, 0));
// Scale the index by multiplying by the entry size.
- ASSERT(StringDictionary::kEntrySize == 3);
+ ASSERT(NameDictionary::kEntrySize == 3);
__ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3.
// Having undefined at this place means the name is not contained.
__ j(equal, &in_dictionary);
if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
- // If we hit a key that is not an internalized string during negative
+ // If we hit a key that is not a unique name during negative
// lookup we have to bailout as this key might be equal to the
// key we are looking for.
- // Check if the entry name is not an internalized string.
+ // Check if the entry name is not a unique name.
+ Label cont;
__ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
__ test_b(FieldOperand(scratch, Map::kInstanceTypeOffset),
kIsInternalizedMask);
- __ j(zero, &maybe_in_dictionary);
+ __ j(not_zero, &cont);
+ __ cmpb(FieldOperand(scratch, Map::kInstanceTypeOffset),
+ static_cast<int8_t>(SYMBOL_TYPE));
+ __ j(not_equal, &maybe_in_dictionary);
+ __ bind(&cont);
}
}
};
-class StringDictionaryLookupStub: public PlatformCodeStub {
+class NameDictionaryLookupStub: public PlatformCodeStub {
public:
enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
- StringDictionaryLookupStub(Register dictionary,
- Register result,
- Register index,
- LookupMode mode)
+ NameDictionaryLookupStub(Register dictionary,
+ Register result,
+ Register index,
+ LookupMode mode)
: dictionary_(dictionary), result_(result), index_(index), mode_(mode) { }
void Generate(MacroAssembler* masm);
Label* miss,
Label* done,
Register properties,
- Handle<String> name,
+ Handle<Name> name,
Register r0);
static void GeneratePositiveLookup(MacroAssembler* masm,
static const int kTotalProbes = 20;
static const int kCapacityOffset =
- StringDictionary::kHeaderSize +
- StringDictionary::kCapacityIndex * kPointerSize;
+ NameDictionary::kHeaderSize +
+ NameDictionary::kCapacityIndex * kPointerSize;
static const int kElementsStartOffset =
- StringDictionary::kHeaderSize +
- StringDictionary::kElementsStartIndex * kPointerSize;
+ NameDictionary::kHeaderSize +
+ NameDictionary::kElementsStartIndex * kPointerSize;
- Major MajorKey() { return StringDictionaryLookup; }
+ Major MajorKey() { return NameDictionaryLookup; }
int MinorKey() {
return DictionaryBits::encode(dictionary_.code()) |
// Generated code falls through if the receiver is a regular non-global
// JS object with slow properties and no interceptors.
-static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
- Register receiver,
- Register r0,
- Register r1,
- Label* miss) {
+static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm,
+ Register receiver,
+ Register r0,
+ Register r1,
+ Label* miss) {
// Register usage:
// receiver: holds the receiver on entry and is unchanged.
// r0: used to hold receiver instance type.
Label done;
// Probe the dictionary.
- StringDictionaryLookupStub::GeneratePositiveLookup(masm,
- miss_label,
- &done,
- elements,
- name,
- r0,
- r1);
+ NameDictionaryLookupStub::GeneratePositiveLookup(masm,
+ miss_label,
+ &done,
+ elements,
+ name,
+ r0,
+ r1);
// If probing finds an entry in the dictionary, r0 contains the
// index into the dictionary. Check that the value is a normal
// property.
__ bind(&done);
const int kElementsStartOffset =
- StringDictionary::kHeaderSize +
- StringDictionary::kElementsStartIndex * kPointerSize;
+ NameDictionary::kHeaderSize +
+ NameDictionary::kElementsStartIndex * kPointerSize;
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
__ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
// Probe the dictionary.
- StringDictionaryLookupStub::GeneratePositiveLookup(masm,
- miss_label,
- &done,
- elements,
- name,
- r0,
- r1);
+ NameDictionaryLookupStub::GeneratePositiveLookup(masm,
+ miss_label,
+ &done,
+ elements,
+ name,
+ r0,
+ r1);
// If probing finds an entry in the dictionary, r0 contains the
// index into the dictionary. Check that the value is a normal
// property that is not read only.
__ bind(&done);
const int kElementsStartOffset =
- StringDictionary::kHeaderSize +
- StringDictionary::kElementsStartIndex * kPointerSize;
+ NameDictionary::kHeaderSize +
+ NameDictionary::kElementsStartIndex * kPointerSize;
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
const int kTypeAndReadOnlyMask =
(PropertyDetails::TypeField::kMask |
}
-// Checks whether a key is an array index string or an internalized string.
-// Falls through if the key is an internalized string.
-static void GenerateKeyStringCheck(MacroAssembler* masm,
- Register key,
- Register map,
- Register hash,
- Label* index_string,
- Label* not_internalized) {
+// Checks whether a key is an array index string or a unique name.
+// Falls through if the key is a unique name.
+static void GenerateKeyNameCheck(MacroAssembler* masm,
+ Register key,
+ Register map,
+ Register hash,
+ Label* index_string,
+ Label* not_unique) {
// Register use:
// key - holds the key and is unchanged. Assumed to be non-smi.
// Scratch registers:
// map - used to hold the map of the key.
// hash - used to hold the hash of the key.
- __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
- __ j(above_equal, not_internalized);
+ Label unique;
+ __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map);
+ __ j(above, not_unique);
+ STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
+ __ j(equal, &unique);
// Is the string an array index, with cached numeric value?
- __ mov(hash, FieldOperand(key, String::kHashFieldOffset));
- __ test(hash, Immediate(String::kContainsCachedArrayIndexMask));
+ __ mov(hash, FieldOperand(key, Name::kHashFieldOffset));
+ __ test(hash, Immediate(Name::kContainsCachedArrayIndexMask));
__ j(zero, index_string);
// Is the string internalized?
STATIC_ASSERT(kInternalizedTag != 0);
__ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsInternalizedMask);
- __ j(zero, not_internalized);
+ __ j(zero, not_unique);
+
+ __ bind(&unique);
}
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
- Label slow, check_string, index_smi, index_string, property_array_property;
+ Label slow, check_name, index_smi, index_name, property_array_property;
Label probe_dictionary, check_number_dictionary;
// Check that the key is a smi.
- __ JumpIfNotSmi(ecx, &check_string);
+ __ JumpIfNotSmi(ecx, &check_name);
__ bind(&index_smi);
// Now the key is known to be a smi. This place is also jumped to from
// where a numeric string is converted to a smi.
__ IncrementCounter(counters->keyed_load_generic_slow(), 1);
GenerateRuntimeGetProperty(masm);
- __ bind(&check_string);
- GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow);
+ __ bind(&check_name);
+ GenerateKeyNameCheck(masm, ecx, eax, ebx, &index_name, &slow);
GenerateKeyedLoadReceiverCheck(
masm, edx, eax, Map::kHasNamedInterceptor, &slow);
__ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
__ ret(0);
- __ bind(&index_string);
+ __ bind(&index_name);
__ IndexFromHash(ebx, ecx);
// Now jump to the place where smi keys are handled.
__ jmp(&index_smi);
// Get the receiver of the function from the stack; 1 ~ return address.
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
- GenerateStringDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
+ GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
// eax: elements
// Search the dictionary placing the result in edi.
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
Label do_call, slow_call, slow_load, slow_reload_receiver;
- Label check_number_dictionary, check_string, lookup_monomorphic_cache;
- Label index_smi, index_string;
+ Label check_number_dictionary, check_name, lookup_monomorphic_cache;
+ Label index_smi, index_name;
// Check that the key is a smi.
- __ JumpIfNotSmi(ecx, &check_string);
+ __ JumpIfNotSmi(ecx, &check_name);
__ bind(&index_smi);
// Now the key is known to be a smi. This place is also jumped to from
__ mov(edi, eax);
__ jmp(&do_call);
- __ bind(&check_string);
- GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call);
+ __ bind(&check_name);
+ GenerateKeyNameCheck(masm, ecx, eax, ebx, &index_name, &slow_call);
- // The key is known to be an internalized string.
+ // The key is known to be a unique name.
// If the receiver is a regular JS object with slow properties then do
// a quick inline probe of the receiver's dictionary.
// Otherwise do the monomorphic cache probe.
__ bind(&slow_call);
// This branch is taken if:
// - the receiver requires boxing or access check,
- // - the key is neither smi nor an internalized string,
+ // - the key is neither smi nor a unique name,
// - the value loaded is not a function,
// - there is hope that the runtime will create a monomorphic call stub
// that will get fetched next time.
__ IncrementCounter(counters->keyed_call_generic_slow(), 1);
GenerateMiss(masm, argc);
- __ bind(&index_string);
+ __ bind(&index_name);
__ IndexFromHash(ebx, ecx);
// Now jump to the place where smi keys are handled.
__ jmp(&index_smi);
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
- // Check if the name is a string.
+ // Check if the name is really a name.
Label miss;
__ JumpIfSmi(ecx, &miss);
- Condition cond = masm->IsObjectStringType(ecx, eax, eax);
+ Condition cond = masm->IsObjectNameType(ecx, eax, eax);
__ j(NegateCondition(cond), &miss);
CallICBase::GenerateNormal(masm, argc);
__ bind(&miss);
// -----------------------------------
Label miss;
- GenerateStringDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
+ GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
// eax: elements
// Search the dictionary placing the result in eax.
Label miss, restore_miss;
- GenerateStringDictionaryReceiverCheck(masm, edx, ebx, edi, &miss);
+ GenerateNameDictionaryReceiverCheck(masm, edx, ebx, edi, &miss);
// A lot of registers are needed for storing to slow case
// objects. Push and restore receiver but rely on
}
+Condition MacroAssembler::IsObjectNameType(Register heap_object,
+ Register map,
+ Register instance_type) {
+ mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
+ movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
+ cmpb(instance_type, static_cast<int8_t>(LAST_NAME_TYPE));
+ return below_equal;
+}
+
+
void MacroAssembler::IsObjectJSObjectType(Register heap_object,
Register map,
Register scratch,
}
+void MacroAssembler::AssertName(Register object) {
+ if (emit_debug_code()) {
+ test(object, Immediate(kSmiTagMask));
+ Check(not_equal, "Operand is a smi and not a name");
+ push(object);
+ mov(object, FieldOperand(object, HeapObject::kMapOffset));
+ CmpInstanceType(object, LAST_NAME_TYPE);
+ pop(object);
+ Check(below_equal, "Operand is not a name");
+ }
+}
+
+
void MacroAssembler::AssertNotSmi(Register object) {
if (emit_debug_code()) {
test(object, Immediate(kSmiTagMask));
Register map,
Register instance_type);
+ // Check if the object in register heap_object is a name. Afterwards the
+ // register map contains the object map and the register instance_type
+ // contains the instance_type. The registers map and instance_type can be the
+ // same in which case it contains the instance type afterwards. Either of the
+ // registers map and instance_type can be the same as heap_object.
+ Condition IsObjectNameType(Register heap_object,
+ Register map,
+ Register instance_type);
+
// Check if a heap object's type is in the JSObject range, not including
// JSFunction. The object's map will be loaded in the map register.
// Any or all of the three registers may be the same.
// Abort execution if argument is not a string, enabled via --debug-code.
void AssertString(Register object);
+ // Abort execution if argument is not a name, enabled via --debug-code.
+ void AssertName(Register object);
+
// ---------------------------------------------------------------------------
// Exception handling
// the property. This function may return false negatives, so miss_label
// must always call a backup property check that is complete.
// This function is safe to call if the receiver has fast properties.
-// Name must be an internalized string and receiver must be a heap object.
+// Name must be unique and receiver must be a heap object.
static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
Label* miss_label,
Register receiver,
- Handle<String> name,
+ Handle<Name> name,
Register r0,
Register r1) {
- ASSERT(name->IsInternalizedString());
+ ASSERT(name->IsUniqueName());
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->negative_lookups(), 1);
__ IncrementCounter(counters->negative_lookups_miss(), 1);
__ j(not_equal, miss_label);
Label done;
- StringDictionaryLookupStub::GenerateNegativeLookup(masm,
- miss_label,
- &done,
- properties,
- name,
- r1);
+ NameDictionaryLookupStub::GenerateNegativeLookup(masm,
+ miss_label,
+ &done,
+ properties,
+ name,
+ r1);
__ bind(&done);
__ DecrementCounter(counters->negative_lookups_miss(), 1);
}
__ JumpIfSmi(receiver, &miss);
// Get the map of the receiver and compute the hash.
- __ mov(offset, FieldOperand(name, String::kHashFieldOffset));
+ __ mov(offset, FieldOperand(name, Name::kHashFieldOffset));
__ add(offset, FieldOperand(receiver, HeapObject::kMapOffset));
__ xor_(offset, flags);
// We mask out the last two bits because they are not part of the hash and
ProbeTable(isolate(), masm, flags, kPrimary, name, receiver, offset, extra);
// Primary miss: Compute hash for secondary probe.
- __ mov(offset, FieldOperand(name, String::kHashFieldOffset));
+ __ mov(offset, FieldOperand(name, Name::kHashFieldOffset));
__ add(offset, FieldOperand(receiver, HeapObject::kMapOffset));
__ xor_(offset, flags);
__ and_(offset, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
void Compile(MacroAssembler* masm,
Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
LookupResult* lookup,
Register receiver,
Register scratch1,
Register scratch3,
Handle<JSObject> interceptor_holder,
LookupResult* lookup,
- Handle<String> name,
+ Handle<Name> name,
const CallOptimization& optimization,
Label* miss_label) {
ASSERT(optimization.is_constant_call());
Register scratch1,
Register scratch2,
Register scratch3,
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> interceptor_holder,
Label* miss_label) {
Register holder =
Handle<JSObject> object,
int index,
Handle<Map> transition,
- Handle<String> name,
+ Handle<Name> name,
Register receiver_reg,
Register name_reg,
Register scratch1,
// property.
static void GenerateCheckPropertyCell(MacroAssembler* masm,
Handle<GlobalObject> global,
- Handle<String> name,
+ Handle<Name> name,
Register scratch,
Label* miss) {
Handle<JSGlobalPropertyCell> cell =
static void GenerateCheckPropertyCells(MacroAssembler* masm,
Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Register scratch,
Label* miss) {
Handle<JSObject> current = object;
Register holder_reg,
Register scratch1,
Register scratch2,
- Handle<String> name,
+ Handle<Name> name,
int save_at_depth,
Label* miss,
PrototypeCheckType check) {
if (!current->HasFastProperties() &&
!current->IsJSGlobalObject() &&
!current->IsJSGlobalProxy()) {
- if (!name->IsInternalizedString()) {
- name = factory()->InternalizeString(name);
+ if (!name->IsUniqueName()) {
+ ASSERT(name->IsString());
+ name = factory()->InternalizeString(Handle<String>::cast(name));
}
ASSERT(current->property_dictionary()->FindEntry(*name) ==
- StringDictionary::kNotFound);
+ NameDictionary::kNotFound);
GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
scratch1, scratch2);
Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Label* success,
Handle<ExecutableAccessorInfo> callback) {
Label miss;
// Probe the dictionary.
Label probe_done, pop_and_miss;
- StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
- &pop_and_miss,
- &probe_done,
- dictionary,
- this->name(),
- scratch2(),
- scratch3());
+ NameDictionaryLookupStub::GeneratePositiveLookup(masm(),
+ &pop_and_miss,
+ &probe_done,
+ dictionary,
+ this->name(),
+ scratch2(),
+ scratch3());
__ bind(&pop_and_miss);
if (must_preserve_dictionary_reg) {
__ pop(dictionary);
// index into the dictionary. Check that the value is the callback.
Register index = scratch2();
const int kElementsStartOffset =
- StringDictionary::kHeaderSize +
- StringDictionary::kElementsStartIndex * kPointerSize;
+ NameDictionary::kHeaderSize +
+ NameDictionary::kElementsStartIndex * kPointerSize;
const int kValueOffset = kElementsStartOffset + kPointerSize;
__ mov(scratch3(),
Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag));
void BaseLoadStubCompiler::NonexistentHandlerFrontend(
Handle<JSObject> object,
Handle<JSObject> last,
- Handle<String> name,
+ Handle<Name> name,
Label* success,
Handle<GlobalObject> global) {
Label miss;
Handle<JSObject> object,
Handle<JSObject> interceptor_holder,
LookupResult* lookup,
- Handle<String> name) {
+ Handle<Name> name) {
ASSERT(interceptor_holder->HasNamedInterceptor());
ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
}
-void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
+void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
if (kind_ == Code::KEYED_CALL_IC) {
__ cmp(ecx, Immediate(name));
__ j(not_equal, miss);
void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Label* miss) {
ASSERT(holder->IsGlobalObject());
Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
Handle<JSObject> holder,
PropertyIndex index,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
CheckType check,
Label* success) {
// ----------- S t a t e -------------
Handle<Code> CallStubCompiler::CompileCallConstant(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
CheckType check,
Handle<JSFunction> function) {
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
Handle<JSGlobalPropertyCell>::null(),
- function, name);
+ function, Handle<String>::cast(name));
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
Handle<GlobalObject> holder,
Handle<JSGlobalPropertyCell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
// -----------------------------------
if (HasCustomCallGenerator(function)) {
- Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
+ Handle<Code> code = CompileCustomCall(
+ object, holder, cell, function, Handle<String>::cast(name));
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
int index,
Handle<Map> transition,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : name
Handle<Code> StoreStubCompiler::CompileStoreCallback(
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<JSFunction> setter) {
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> receiver,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : name
Handle<Code> StoreStubCompiler::CompileStoreGlobal(
Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : name
Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
int index,
Handle<Map> transition,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : key
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
Handle<JSObject> object,
Handle<JSObject> last,
- Handle<String> name,
+ Handle<Name> name,
Handle<GlobalObject> global) {
Label success;
}
-void KeyedLoadStubCompiler::GenerateNameCheck(Handle<String> name,
+void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
Register name_reg,
Label* miss) {
__ cmp(name_reg, Immediate(name));
Handle<JSObject> object,
Handle<GlobalObject> global,
Handle<JSGlobalPropertyCell> cell,
- Handle<String> name,
+ Handle<Name> name,
bool is_dont_delete) {
Label success, miss;
Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps,
CodeHandleList* handlers,
- Handle<String> name,
+ Handle<Name> name,
Code::StubType type,
IcCheckType check) {
Label miss;
object->elements()->length() == 0) {
Handle<Map> map(object->map());
for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
- Handle<String> key(map->instance_descriptors()->GetKey(i), isolate_);
+ Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_);
+ // TODO(rossberg): Should this throw?
+ if (!name->IsString()) continue;
+ Handle<String> key = Handle<String>::cast(name);
PropertyDetails details = map->instance_descriptors()->GetDetails(i);
if (details.IsDontEnum() || details.IsDeleted()) continue;
Handle<Object> property;
}
}
+ void AppendHex(uint32_t n) {
+ Vector<char> buffer(utf8_buffer_ + utf8_pos_, kUtf8BufferSize - utf8_pos_);
+ int size = OS::SNPrintF(buffer, "%x", n);
+ if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
+ utf8_pos_ += size;
+ }
+ }
+
const char* get() { return utf8_buffer_; }
int size() const { return utf8_pos_; }
SmartArrayPointer<char> str =
String::cast(key)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
ApiEvent("api,check-security,\"%s\"\n", *str);
+ } else if (key->IsSymbol()) {
+ ApiEvent("api,check-security,symbol(hash %x)\n", Symbol::cast(key)->Hash());
} else if (key->IsUndefined()) {
ApiEvent("api,check-security,undefined\n");
} else {
void Logger::ApiNamedPropertyAccess(const char* tag,
JSObject* holder,
Object* name) {
- ASSERT(name->IsString());
+ ASSERT(name->IsName());
if (!log_->IsEnabled() || !FLAG_log_api) return;
String* class_name_obj = holder->class_name();
SmartArrayPointer<char> class_name =
class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- SmartArrayPointer<char> property_name =
- String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name);
+ if (name->IsString()) {
+ SmartArrayPointer<char> property_name =
+ String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+ ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name);
+ } else {
+ uint32_t hash = Symbol::cast(name)->Hash();
+ ApiEvent("api,%s,\"%s\",symbol(hash %x)\n", tag, *class_name, hash);
+ }
}
void Logger::ApiIndexedPropertyAccess(const char* tag,
LOGGER->DeleteEvent(name, object);
}
-void Logger::CallbackEventInternal(const char* prefix, const char* name,
+void Logger::CallbackEventInternal(const char* prefix, Name* name,
Address entry_point) {
if (!log_->IsEnabled() || !FLAG_log_code) return;
LogMessageBuilder msg(this);
kLogEventsNames[CODE_CREATION_EVENT],
kLogEventsNames[CALLBACK_TAG]);
msg.AppendAddress(entry_point);
- msg.Append(",1,\"%s%s\"", prefix, name);
+ if (name->IsString()) {
+ SmartArrayPointer<char> str =
+ String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+ msg.Append(",1,\"%s%s\"", prefix, *str);
+ } else {
+ msg.Append(",1,symbol(hash %x)", prefix, Name::cast(name)->Hash());
+ }
msg.Append('\n');
msg.WriteToLogFile();
}
-void Logger::CallbackEvent(String* name, Address entry_point) {
+void Logger::CallbackEvent(Name* name, Address entry_point) {
if (!log_->IsEnabled() || !FLAG_log_code) return;
- SmartArrayPointer<char> str =
- name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- CallbackEventInternal("", *str, entry_point);
+ CallbackEventInternal("", name, entry_point);
}
-void Logger::GetterCallbackEvent(String* name, Address entry_point) {
+void Logger::GetterCallbackEvent(Name* name, Address entry_point) {
if (!log_->IsEnabled() || !FLAG_log_code) return;
- SmartArrayPointer<char> str =
- name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- CallbackEventInternal("get ", *str, entry_point);
+ CallbackEventInternal("get ", name, entry_point);
}
-void Logger::SetterCallbackEvent(String* name, Address entry_point) {
+void Logger::SetterCallbackEvent(Name* name, Address entry_point) {
if (!log_->IsEnabled() || !FLAG_log_code) return;
- SmartArrayPointer<char> str =
- name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- CallbackEventInternal("set ", *str, entry_point);
+ CallbackEventInternal("set ", name, entry_point);
}
void Logger::CodeCreateEvent(LogEventsAndTags tag,
Code* code,
- String* name) {
+ Name* name) {
if (!is_logging_code_events()) return;
if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
name_buffer_->Reset();
name_buffer_->AppendBytes(kLogEventsNames[tag]);
name_buffer_->AppendByte(':');
- name_buffer_->AppendString(name);
+ if (name->IsString()) {
+ name_buffer_->AppendString(String::cast(name));
+ } else {
+ name_buffer_->AppendBytes("symbol(hash ");
+ name_buffer_->AppendHex(Name::cast(name)->Hash());
+ name_buffer_->AppendByte(')');
+ }
}
if (code_event_handler_ != NULL) {
IssueCodeAddedEvent(code, NULL, name_buffer_->get(), name_buffer_->size());
kLogEventsNames[tag],
code->kind());
msg.AppendAddress(code->address());
- msg.Append(",%d,\"", code->ExecutableSize());
- msg.AppendDetailed(name, false);
- msg.Append('"');
+ msg.Append(",%d,", code->ExecutableSize());
+ if (name->IsString()) {
+ msg.Append('"');
+ msg.AppendDetailed(String::cast(name), false);
+ msg.Append('"');
+ } else {
+ msg.Append("symbol(hash %x)", Name::cast(name)->Hash());
+ }
msg.Append('\n');
msg.WriteToLogFile();
}
void Logger::CodeCreateEvent(LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
- String* name) {
+ Name* name) {
if (!is_logging_code_events()) return;
if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
name_buffer_->Reset();
name_buffer_->AppendBytes(kLogEventsNames[tag]);
name_buffer_->AppendByte(':');
name_buffer_->AppendBytes(ComputeMarker(code));
- name_buffer_->AppendString(name);
+ if (name->IsString()) {
+ name_buffer_->AppendString(String::cast(name));
+ } else {
+ name_buffer_->AppendBytes("symbol(hash ");
+ name_buffer_->AppendHex(Name::cast(name)->Hash());
+ name_buffer_->AppendByte(')');
+ }
}
if (code_event_handler_ != NULL) {
Script* script =
return;
LogMessageBuilder msg(this);
- SmartArrayPointer<char> str =
- name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
msg.Append("%s,%s,%d,",
kLogEventsNames[CODE_CREATION_EVENT],
kLogEventsNames[tag],
code->kind());
msg.AppendAddress(code->address());
- msg.Append(",%d,\"%s\",", code->ExecutableSize(), *str);
+ msg.Append(",%d,", code->ExecutableSize());
+ if (name->IsString()) {
+ SmartArrayPointer<char> str =
+ String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+ msg.Append("\"%s\"", *str);
+ } else {
+ msg.Append("symbol(hash %x)", Name::cast(name)->Hash());
+ }
+ msg.Append(',');
msg.AppendAddress(shared->address());
msg.Append(",%s", ComputeMarker(code));
msg.Append('\n');
void Logger::CodeCreateEvent(LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
- String* source, int line) {
+ Name* source, int line) {
if (!is_logging_code_events()) return;
if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
name_buffer_->Reset();
name_buffer_->AppendBytes(ComputeMarker(code));
name_buffer_->AppendString(shared->DebugName());
name_buffer_->AppendByte(' ');
- name_buffer_->AppendString(source);
+ if (source->IsString()) {
+ name_buffer_->AppendString(String::cast(source));
+ } else {
+ name_buffer_->AppendBytes("symbol(hash ");
+ name_buffer_->AppendHex(Name::cast(source)->Hash());
+ name_buffer_->AppendByte(')');
+ }
name_buffer_->AppendByte(':');
name_buffer_->AppendInt(line);
}
LogMessageBuilder msg(this);
SmartArrayPointer<char> name =
shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- SmartArrayPointer<char> sourcestr =
- source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
msg.Append("%s,%s,%d,",
kLogEventsNames[CODE_CREATION_EVENT],
kLogEventsNames[tag],
code->kind());
msg.AppendAddress(code->address());
- msg.Append(",%d,\"%s %s:%d\",",
- code->ExecutableSize(),
- *name,
- *sourcestr,
- line);
+ msg.Append(",%d,\"%s ", code->ExecutableSize(), *name);
+ if (source->IsString()) {
+ SmartArrayPointer<char> sourcestr =
+ String::cast(source)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+ msg.Append("%s", *sourcestr);
+ } else {
+ msg.Append("symbol(hash %x)", Name::cast(source)->Hash());
+ }
+ msg.Append(":%d\",", line);
msg.AppendAddress(shared->address());
msg.Append(",%s", ComputeMarker(code));
msg.Append('\n');
}
-void Logger::SuspectReadEvent(String* name, Object* obj) {
+void Logger::SuspectReadEvent(Name* name, Object* obj) {
if (!log_->IsEnabled() || !FLAG_log_suspect) return;
LogMessageBuilder msg(this);
String* class_name = obj->IsJSObject()
msg.Append("suspect-read,");
msg.Append(class_name);
msg.Append(',');
- msg.Append('"');
- msg.Append(name);
- msg.Append('"');
+ if (name->IsString()) {
+ msg.Append('"');
+ msg.Append(String::cast(name));
+ msg.Append('"');
+ } else {
+ msg.Append("symbol(hash %x)", Name::cast(name)->Hash());
+ }
msg.Append('\n');
msg.WriteToLogFile();
}
for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
if (!obj->IsExecutableAccessorInfo()) continue;
ExecutableAccessorInfo* ai = ExecutableAccessorInfo::cast(obj);
- if (!ai->name()->IsString()) continue;
- String* name = String::cast(ai->name());
+ if (!ai->name()->IsName()) continue;
Address getter_entry = v8::ToCData<Address>(ai->getter());
+ Name* name = Name::cast(ai->name());
if (getter_entry != 0) {
PROFILE(ISOLATE, GetterCallbackEvent(name, getter_entry));
}
// Emits an event that an undefined property was read from an
// object.
- void SuspectReadEvent(String* name, Object* obj);
+ void SuspectReadEvent(Name* name, Object* obj);
// Emits an event when a message is put on or read from a debugging queue.
// DebugTag lets us put a call-site specific label on the event.
// ==== Events logged by --log-code. ====
// Emits a code event for a callback function.
- void CallbackEvent(String* name, Address entry_point);
- void GetterCallbackEvent(String* name, Address entry_point);
- void SetterCallbackEvent(String* name, Address entry_point);
+ void CallbackEvent(Name* name, Address entry_point);
+ void GetterCallbackEvent(Name* name, Address entry_point);
+ void SetterCallbackEvent(Name* name, Address entry_point);
// Emits a code create event.
void CodeCreateEvent(LogEventsAndTags tag,
Code* code, const char* source);
void CodeCreateEvent(LogEventsAndTags tag,
- Code* code, String* name);
+ Code* code, Name* name);
void CodeCreateEvent(LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
- String* name);
+ Name* name);
void CodeCreateEvent(LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
- String* source, int line);
+ Name* source, int line);
void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count);
void CodeMovingGCEvent();
// Emits a code create event for a RegExp.
// Emits callback event messages.
void CallbackEventInternal(const char* prefix,
- const char* name,
+ Name* name,
Address entry_point);
// Internal configurable move event.
info->number_of_fast_used_fields_ += map()->NextFreePropertyIndex();
info->number_of_fast_unused_fields_ += map()->unused_property_fields();
} else {
- StringDictionary* dict = property_dictionary();
+ NameDictionary* dict = property_dictionary();
info->number_of_slow_used_properties_ += dict->NumberOfElements();
info->number_of_slow_unused_properties_ +=
dict->Capacity() - dict->NumberOfElements();
bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) {
if (valid_entries == -1) valid_entries = number_of_descriptors();
- String* current_key = NULL;
+ Name* current_key = NULL;
uint32_t current = 0;
for (int i = 0; i < number_of_descriptors(); i++) {
- String* key = GetSortedKey(i);
+ Name* key = GetSortedKey(i);
if (key == current_key) {
PrintDescriptors();
return false;
bool TransitionArray::IsSortedNoDuplicates(int valid_entries) {
ASSERT(valid_entries == -1);
- String* current_key = NULL;
+ Name* current_key = NULL;
uint32_t current = 0;
for (int i = 0; i < number_of_transitions(); i++) {
- String* key = GetSortedKey(i);
+ Name* key = GetSortedKey(i);
if (key == current_key) {
PrintTransitions();
return false;
}
-MaybeObject* Object::GetProperty(String* key) {
+MaybeObject* Object::GetProperty(Name* key) {
PropertyAttributes attributes;
return GetPropertyWithReceiver(this, key, &attributes);
}
-MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
+MaybeObject* Object::GetProperty(Name* key, PropertyAttributes* attributes) {
return GetPropertyWithReceiver(this, key, attributes);
}
bool JSObject::TryTransitionToField(Handle<JSObject> object,
- Handle<String> key) {
+ Handle<Name> key) {
if (!object->map()->HasTransitionArray()) return false;
Handle<TransitionArray> transitions(object->map()->transitions());
int transition = transitions->Search(*key);
// there are three entries in this array it should be called with low=0 and
// high=2.
template<SearchMode search_mode, typename T>
-int BinarySearch(T* array, String* name, int low, int high, int valid_entries) {
+int BinarySearch(T* array, Name* name, int low, int high, int valid_entries) {
uint32_t hash = name->Hash();
int limit = high;
while (low != high) {
int mid = (low + high) / 2;
- String* mid_name = array->GetSortedKey(mid);
+ Name* mid_name = array->GetSortedKey(mid);
uint32_t mid_hash = mid_name->Hash();
if (mid_hash >= hash) {
for (; low <= limit; ++low) {
int sort_index = array->GetSortedKeyIndex(low);
- String* entry = array->GetKey(sort_index);
+ Name* entry = array->GetKey(sort_index);
if (entry->Hash() != hash) break;
if (entry->Equals(name)) {
if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
// Perform a linear search in this fixed array. len is the number of entry
// indices that are valid.
template<SearchMode search_mode, typename T>
-int LinearSearch(T* array, String* name, int len, int valid_entries) {
+int LinearSearch(T* array, Name* name, int len, int valid_entries) {
uint32_t hash = name->Hash();
if (search_mode == ALL_ENTRIES) {
for (int number = 0; number < len; number++) {
int sorted_index = array->GetSortedKeyIndex(number);
- String* entry = array->GetKey(sorted_index);
+ Name* entry = array->GetKey(sorted_index);
uint32_t current_hash = entry->Hash();
if (current_hash > hash) break;
if (current_hash == hash && entry->Equals(name)) return sorted_index;
} else {
ASSERT(len >= valid_entries);
for (int number = 0; number < valid_entries; number++) {
- String* entry = array->GetKey(number);
+ Name* entry = array->GetKey(number);
uint32_t current_hash = entry->Hash();
if (current_hash == hash && entry->Equals(name)) return number;
}
template<SearchMode search_mode, typename T>
-int Search(T* array, String* name, int valid_entries) {
+int Search(T* array, Name* name, int valid_entries) {
if (search_mode == VALID_ENTRIES) {
SLOW_ASSERT(array->IsSortedNoDuplicates(valid_entries));
} else {
}
-int DescriptorArray::Search(String* name, int valid_descriptors) {
+int DescriptorArray::Search(Name* name, int valid_descriptors) {
return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors);
}
-int DescriptorArray::SearchWithCache(String* name, Map* map) {
+int DescriptorArray::SearchWithCache(Name* name, Map* map) {
int number_of_own_descriptors = map->NumberOfOwnDescriptors();
if (number_of_own_descriptors == 0) return kNotFound;
void Map::LookupDescriptor(JSObject* holder,
- String* name,
+ Name* name,
LookupResult* result) {
DescriptorArray* descriptors = this->instance_descriptors();
int number = descriptors->SearchWithCache(name, this);
void Map::LookupTransition(JSObject* holder,
- String* name,
+ Name* name,
LookupResult* result) {
if (HasTransitionArray()) {
TransitionArray* transition_array = transitions();
}
-String* DescriptorArray::GetKey(int descriptor_number) {
+Name* DescriptorArray::GetKey(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors());
- return String::cast(get(ToKeyIndex(descriptor_number)));
+ return Name::cast(get(ToKeyIndex(descriptor_number)));
}
}
-String* DescriptorArray::GetSortedKey(int descriptor_number) {
+Name* DescriptorArray::GetSortedKey(int descriptor_number) {
return GetKey(GetSortedKeyIndex(descriptor_number));
}
int insertion;
for (insertion = descriptor_number; insertion > 0; --insertion) {
- String* key = GetSortedKey(insertion - 1);
+ Name* key = GetSortedKey(insertion - 1);
if (key->Hash() <= hash) break;
SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
}
int insertion;
for (insertion = descriptor_number; insertion > 0; --insertion) {
- String* key = GetSortedKey(insertion - 1);
+ Name* key = GetSortedKey(insertion - 1);
if (key->Hash() <= hash) break;
SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
}
CAST_ACCESSOR(ExternalAsciiString)
CAST_ACCESSOR(ExternalTwoByteString)
CAST_ACCESSOR(Symbol)
+CAST_ACCESSOR(Name)
CAST_ACCESSOR(JSReceiver)
CAST_ACCESSOR(JSObject)
CAST_ACCESSOR(Smi)
CAST_ACCESSOR(HeapObject)
CAST_ACCESSOR(HeapNumber)
-CAST_ACCESSOR(Name)
CAST_ACCESSOR(Oddball)
CAST_ACCESSOR(JSGlobalPropertyCell)
CAST_ACCESSOR(SharedFunctionInfo)
}
+bool Name::Equals(Name* other) {
+ if (other == this) return true;
+ if (this->IsUniqueName() && other->IsUniqueName()) return false;
+ return String::cast(this)->SlowEquals(String::cast(other));
+}
+
+
bool String::Equals(String* other) {
if (other == this) return true;
- if (StringShape(this).IsInternalized() &&
- StringShape(other).IsInternalized()) {
+ if (this->IsInternalizedString() && other->IsInternalizedString()) {
return false;
}
return SlowEquals(other);
int HeapObject::SizeFromMap(Map* map) {
int instance_size = map->instance_size();
if (instance_size != kVariableSizeSentinel) return instance_size;
- // We can ignore the "internalized" bit becase it is only set for strings
+ // We can ignore the "internalized" bit because it is only set for strings
// and thus implies a string type.
int instance_type =
static_cast<int>(map->instance_type()) & ~kIsInternalizedMask;
}
-MaybeObject* Map::AddTransition(String* key,
+MaybeObject* Map::AddTransition(Name* key,
Map* target,
SimpleTransitionFlag flag) {
if (HasTransitionArray()) return transitions()->CopyInsert(key, target);
}
-StringDictionary* JSObject::property_dictionary() {
+NameDictionary* JSObject::property_dictionary() {
ASSERT(!HasFastProperties());
- return StringDictionary::cast(properties());
+ return NameDictionary::cast(properties());
}
}
+bool Name::AsArrayIndex(uint32_t* index) {
+ return IsString() && String::cast(this)->AsArrayIndex(index);
+}
+
+
bool String::AsArrayIndex(uint32_t* index) {
uint32_t field = hash_field();
if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
}
-bool JSReceiver::HasProperty(String* name) {
+bool JSReceiver::HasProperty(Name* name) {
if (IsJSProxy()) {
return JSProxy::cast(this)->HasPropertyWithHandler(name);
}
}
-bool JSReceiver::HasLocalProperty(String* name) {
+bool JSReceiver::HasLocalProperty(Name* name) {
if (IsJSProxy()) {
return JSProxy::cast(this)->HasPropertyWithHandler(name);
}
}
-PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) {
+PropertyAttributes JSReceiver::GetPropertyAttribute(Name* key) {
uint32_t index;
if (IsJSObject() && key->AsArrayIndex(&index)) {
return GetElementAttribute(index);
Object* key,
Object* value,
PropertyDetails details) {
- ASSERT(!key->IsString() ||
+ ASSERT(!key->IsName() ||
details.IsDeleted() ||
details.dictionary_index() > 0);
int index = HashTable<Shape, Key>::EntryToIndex(entry);
}
-bool StringDictionaryShape::IsMatch(String* key, Object* other) {
+bool NameDictionaryShape::IsMatch(Name* key, Object* other) {
// We know that all entries in a hash table had their hash keys created.
// Use that knowledge to have fast failure.
- if (key->Hash() != String::cast(other)->Hash()) return false;
- return key->Equals(String::cast(other));
+ if (key->Hash() != Name::cast(other)->Hash()) return false;
+ return key->Equals(Name::cast(other));
}
-uint32_t StringDictionaryShape::Hash(String* key) {
+uint32_t NameDictionaryShape::Hash(Name* key) {
return key->Hash();
}
-uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
- return String::cast(other)->Hash();
+uint32_t NameDictionaryShape::HashForObject(Name* key, Object* other) {
+ return Name::cast(other)->Hash();
}
-MaybeObject* StringDictionaryShape::AsObject(String* key) {
+MaybeObject* NameDictionaryShape::AsObject(Name* key) {
return key;
}
DescriptorArray* descs = map()->instance_descriptors();
for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
PrintF(out, " ");
- descs->GetKey(i)->StringPrint(out);
+ descs->GetKey(i)->NamePrint(out);
PrintF(out, ": ");
switch (descs->GetType(i)) {
case FIELD: {
TransitionArray* transitions = map()->transitions();
for (int i = 0; i < transitions->number_of_transitions(); i++) {
PrintF(out, " ");
- transitions->GetKey(i)->StringPrint(out);
+ transitions->GetKey(i)->NamePrint(out);
PrintF(out, ": ");
switch (transitions->GetTargetDetails(i).type()) {
case FIELD: {
}
+void Name::NamePrint(FILE* out) {
+ if (IsString())
+ String::cast(this)->StringPrint(out);
+ else
+ ShortPrint();
+}
+
+
// This method is only meant to be called from gdb for debugging purposes.
// Since the string can also be in two-byte encoding, non-ASCII characters
// will be ignored in the output.
PrintF(out, "Transition array %d\n", number_of_transitions());
for (int i = 0; i < number_of_transitions(); i++) {
PrintF(out, " %d: ", i);
- GetKey(i)->StringPrint(out);
+ GetKey(i)->NamePrint(out);
PrintF(out, ": ");
switch (GetTargetDetails(i).type()) {
case FIELD: {
}
-void Object::Lookup(String* name, LookupResult* result) {
+void Object::Lookup(Name* name, LookupResult* result) {
Object* holder = NULL;
if (IsJSReceiver()) {
holder = this;
MaybeObject* Object::GetPropertyWithReceiver(Object* receiver,
- String* name,
+ Name* name,
PropertyAttributes* attributes) {
LookupResult result(name->GetIsolate());
Lookup(name, &result);
MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver,
Object* structure,
- String* name) {
+ Name* name) {
Isolate* isolate = name->GetIsolate();
// To accommodate both the old and the new api we switch on the
// data structure used to store the callbacks. Eventually foreign
ARRAY_SIZE(args)));
return isolate->Throw(*error);
}
+ // TODO(rossberg): Handling symbols in the API requires changing the API,
+ // so we do not support it for now.
+ if (name->IsSymbol()) return isolate->heap()->undefined_value();
Object* fun_obj = data->getter();
v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
if (call_fun == NULL) return isolate->heap()->undefined_value();
HandleScope scope(isolate);
JSObject* self = JSObject::cast(receiver);
- Handle<String> key(name);
+ Handle<String> key(String::cast(name));
LOG(isolate, ApiNamedPropertyAccess("load", self, name));
CustomArguments args(isolate, data->data(), self, this);
v8::AccessorInfo info(args.end());
MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
- String* name_raw) {
+ Name* name_raw) {
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
Handle<Object> receiver(receiver_raw, isolate);
}
-Handle<Object> Object::GetProperty(Handle<Object> object, Handle<String> name) {
+Handle<Object> Object::GetProperty(Handle<Object> object, Handle<Name> name) {
// TODO(rossberg): The index test should not be here but in the GetProperty
// method (or somewhere else entirely). Needs more global clean-up.
uint32_t index;
- if (name->AsArrayIndex(&index)) return GetElement(object, index);
+ if (name->AsArrayIndex(&index))
+ return GetElement(object, index);
Isolate* isolate = object->IsHeapObject()
? Handle<HeapObject>::cast(object)->GetIsolate()
: Isolate::Current();
MaybeObject* JSObject::GetPropertyWithFailedAccessCheck(
Object* receiver,
LookupResult* result,
- String* name,
+ Name* name,
PropertyAttributes* attributes) {
if (result->IsProperty()) {
switch (result->type()) {
PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
Object* receiver,
LookupResult* result,
- String* name,
+ Name* name,
bool continue_search) {
if (result->IsProperty()) {
switch (result->type()) {
Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object,
- Handle<String> key,
+ Handle<Name> key,
Handle<Object> value,
PropertyDetails details) {
CALL_HEAP_FUNCTION(object->GetIsolate(),
}
-MaybeObject* JSObject::SetNormalizedProperty(String* name,
+MaybeObject* JSObject::SetNormalizedProperty(Name* name,
Object* value,
PropertyDetails details) {
ASSERT(!HasFastProperties());
int entry = property_dictionary()->FindEntry(name);
- if (entry == StringDictionary::kNotFound) {
+ if (entry == NameDictionary::kNotFound) {
Object* store_value = value;
if (IsGlobalObject()) {
Heap* heap = name->GetHeap();
property_dictionary()->Add(name, store_value, details);
if (!maybe_dict->ToObject(&dict)) return maybe_dict;
}
- set_properties(StringDictionary::cast(dict));
+ set_properties(NameDictionary::cast(dict));
return value;
}
}
-MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) {
+MaybeObject* JSObject::DeleteNormalizedProperty(Name* name, DeleteMode mode) {
ASSERT(!HasFastProperties());
- StringDictionary* dictionary = property_dictionary();
+ NameDictionary* dictionary = property_dictionary();
int entry = dictionary->FindEntry(name);
- if (entry != StringDictionary::kNotFound) {
+ if (entry != NameDictionary::kNotFound) {
// If we have a global object set the cell to the hole.
if (IsGlobalObject()) {
PropertyDetails details = dictionary->DetailsAt(entry);
Handle<Object> Object::GetProperty(Handle<Object> object,
Handle<Object> receiver,
LookupResult* result,
- Handle<String> key,
+ Handle<Name> key,
PropertyAttributes* attributes) {
Isolate* isolate = object->IsHeapObject()
? Handle<HeapObject>::cast(object)->GetIsolate()
MaybeObject* Object::GetProperty(Object* receiver,
LookupResult* result,
- String* name,
+ Name* name,
PropertyAttributes* attributes) {
// Make sure that the top context does not change when doing
// callbacks or interceptor calls.
MaybeObject* Object::GetHash(CreationFlag flag) {
- // The object is either a number, a string, an odd-ball,
+ // The object is either a number, a name, an odd-ball,
// a real JS object, or a Harmony proxy.
if (IsNumber()) {
uint32_t hash = ComputeLongHash(double_to_uint64(Number()));
bool Object::SameValue(Object* other) {
if (other == this) return true;
- // The object is either a number, a string, an odd-ball,
+ // The object is either a number, a name, an odd-ball,
// a real JS object, or a Harmony proxy.
if (IsNumber() && other->IsNumber()) {
double this_value = Number();
MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
- String* name,
+ Name* name,
Object* value,
int field_index) {
if (map()->unused_property_fields() == 0) {
}
-static bool IsIdentifier(UnicodeCache* cache, String* string) {
+static bool IsIdentifier(UnicodeCache* cache, Name* name) {
// Checks whether the buffer contains an identifier (no escape).
+ if (!name->IsString()) return false;
+ String* string = String::cast(name);
if (string->length() == 0) return false;
ConsStringIteratorOp op;
StringCharacterStream stream(string, &op);
}
-MaybeObject* JSObject::AddFastProperty(String* name,
+MaybeObject* JSObject::AddFastProperty(Name* name,
Object* value,
PropertyAttributes attributes,
StoreFromKeyed store_mode) {
map()->instance_descriptors()->Search(
name, map()->NumberOfOwnDescriptors()));
- // Normalize the object if the name is an actual string (not the
+ // Normalize the object if the name is an actual name (not the
// hidden strings) and is not a real identifier.
// Normalize the object if it will have too many fast properties.
Isolate* isolate = GetHeap()->isolate();
MaybeObject* JSObject::AddConstantFunctionProperty(
- String* name,
+ Name* name,
JSFunction* function,
PropertyAttributes attributes) {
// Allocate new instance descriptors with (name, function) added
// Add property in slow mode
-MaybeObject* JSObject::AddSlowProperty(String* name,
+MaybeObject* JSObject::AddSlowProperty(Name* name,
Object* value,
PropertyAttributes attributes) {
ASSERT(!HasFastProperties());
- StringDictionary* dict = property_dictionary();
+ NameDictionary* dict = property_dictionary();
Object* store_value = value;
if (IsGlobalObject()) {
// In case name is an orphaned property reuse the cell.
int entry = dict->FindEntry(name);
- if (entry != StringDictionary::kNotFound) {
+ if (entry != NameDictionary::kNotFound) {
store_value = dict->ValueAt(entry);
JSGlobalPropertyCell::cast(store_value)->set_value(value);
// Assign an enumeration index to the property and update
{ MaybeObject* maybe_result = dict->Add(name, store_value, details);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
- if (dict != result) set_properties(StringDictionary::cast(result));
+ if (dict != result) set_properties(NameDictionary::cast(result));
return value;
}
-MaybeObject* JSObject::AddProperty(String* name,
+MaybeObject* JSObject::AddProperty(Name* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
if (strict_mode == kNonStrictMode) {
return value;
} else {
- Handle<Object> args[1] = {Handle<String>(name)};
+ Handle<Object> args[1] = {Handle<Name>(name)};
return isolate->Throw(
*FACTORY->NewTypeError("object_not_extensible",
HandleVector(args, 1)));
void JSObject::EnqueueChangeRecord(Handle<JSObject> object,
const char* type_str,
- Handle<String> name,
+ Handle<Name> name,
Handle<Object> old_value) {
Isolate* isolate = object->GetIsolate();
HandleScope scope(isolate);
MaybeObject* JSObject::SetPropertyPostInterceptor(
- String* name,
+ Name* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
}
-MaybeObject* JSObject::ReplaceSlowProperty(String* name,
+MaybeObject* JSObject::ReplaceSlowProperty(Name* name,
Object* value,
PropertyAttributes attributes) {
- StringDictionary* dictionary = property_dictionary();
+ NameDictionary* dictionary = property_dictionary();
int old_index = dictionary->FindEntry(name);
int new_enumeration_index = 0; // 0 means "Use the next available index."
if (old_index != -1) {
MaybeObject* JSObject::ConvertTransitionToMapTransition(
int transition_index,
- String* name,
+ Name* name,
Object* new_value,
PropertyAttributes attributes) {
Map* old_map = map();
}
-MaybeObject* JSObject::ConvertDescriptorToField(String* name,
+MaybeObject* JSObject::ConvertDescriptorToField(Name* name,
Object* new_value,
PropertyAttributes attributes) {
if (map()->unused_property_fields() == 0 &&
MaybeObject* JSObject::SetPropertyWithInterceptor(
- String* name,
+ Name* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode) {
+ // TODO(rossberg): Support symbols in the API.
+ if (name->IsSymbol()) return value;
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
Handle<JSObject> this_handle(this);
- Handle<String> name_handle(name);
+ Handle<String> name_handle(String::cast(name));
Handle<Object> value_handle(value, isolate);
Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
if (!interceptor->setter()->IsUndefined()) {
Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
- Handle<String> key,
+ Handle<Name> key,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode) {
}
-MaybeObject* JSReceiver::SetProperty(String* name,
+MaybeObject* JSReceiver::SetProperty(Name* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
- String* name,
+ Name* name,
Object* value,
JSObject* holder,
StrictModeFlag strict_mode) {
ARRAY_SIZE(args)));
return isolate->Throw(*error);
}
+ // TODO(rossberg): Support symbols in the API.
+ if (name->IsSymbol()) return value;
Object* call_obj = data->setter();
v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
if (call_fun == NULL) return value;
- Handle<String> key(name);
+ Handle<String> key(String::cast(name));
LOG(isolate, ApiNamedPropertyAccess("store", this, name));
CustomArguments args(isolate, data->data(), this, JSObject::cast(holder));
v8::AccessorInfo info(args.end());
if (strict_mode == kNonStrictMode) {
return value;
}
- Handle<String> key(name);
+ Handle<Name> key(name);
Handle<Object> holder_handle(holder, isolate);
Handle<Object> args[2] = { key, holder_handle };
return isolate->Throw(
}
MaybeObject* JSObject::SetPropertyViaPrototypes(
- String* name,
+ Name* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
ASSERT(array->NumberOfSlackDescriptors() >= nof_callbacks);
- // Ensure the keys are internalized strings before writing them into the
+ // Ensure the keys are unique names before writing them into the
// instance descriptor. Since it may cause a GC, it has to be done before we
// temporarily put the heap in an invalid state while appending descriptors.
for (int i = 0; i < nof_callbacks; ++i) {
Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i)));
- Handle<String> key =
- isolate->factory()->InternalizedStringFromString(
- Handle<String>(String::cast(entry->name())));
- entry->set_name(*key);
+ if (!entry->name()->IsUniqueName()) {
+ Handle<String> key =
+ isolate->factory()->InternalizedStringFromString(
+ Handle<String>(String::cast(entry->name())));
+ entry->set_name(*key);
+ }
}
int nof = map->NumberOfOwnDescriptors();
// precedence over previously added callbacks with that name.
for (int i = nof_callbacks - 1; i >= 0; i--) {
AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
- String* key = String::cast(entry->name());
+ Name* key = Name::cast(entry->name());
// Check if a descriptor with this name already exists before writing.
if (array->Search(key, nof) == DescriptorArray::kNotFound) {
CallbacksDescriptor desc(key, entry, entry->property_attributes());
}
-void JSObject::LocalLookupRealNamedProperty(String* name,
- LookupResult* result) {
+void JSObject::LocalLookupRealNamedProperty(Name* name, LookupResult* result) {
if (IsJSGlobalProxy()) {
Object* proto = GetPrototype();
if (proto->IsNull()) return result->NotFound();
}
int entry = property_dictionary()->FindEntry(name);
- if (entry != StringDictionary::kNotFound) {
+ if (entry != NameDictionary::kNotFound) {
Object* value = property_dictionary()->ValueAt(entry);
if (IsGlobalObject()) {
PropertyDetails d = property_dictionary()->DetailsAt(entry);
}
-void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) {
+void JSObject::LookupRealNamedProperty(Name* name, LookupResult* result) {
LocalLookupRealNamedProperty(name, result);
if (result->IsFound()) return;
}
-void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
+void JSObject::LookupRealNamedPropertyInPrototypes(Name* name,
LookupResult* result) {
Isolate* isolate = GetIsolate();
Heap* heap = isolate->heap();
// We only need to deal with CALLBACKS and INTERCEPTORS
MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
LookupResult* result,
- String* name,
+ Name* name,
Object* value,
bool check_prototype,
StrictModeFlag strict_mode) {
MaybeObject* JSReceiver::SetProperty(LookupResult* result,
- String* key,
+ Name* key,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
}
-bool JSProxy::HasPropertyWithHandler(String* name_raw) {
+bool JSProxy::HasPropertyWithHandler(Name* name_raw) {
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
Handle<Object> receiver(this, isolate);
MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
JSReceiver* receiver_raw,
- String* name_raw,
+ Name* name_raw,
Object* value_raw,
PropertyAttributes attributes,
StrictModeFlag strict_mode) {
MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
JSReceiver* receiver_raw,
- String* name_raw,
+ Name* name_raw,
Object* value_raw,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
Isolate* isolate = GetIsolate();
Handle<JSProxy> proxy(this);
Handle<JSReceiver> receiver(receiver_raw);
- Handle<String> name(name_raw);
+ Handle<Name> name(name_raw);
Handle<Object> value(value_raw, isolate);
Handle<Object> handler(this->handler(), isolate); // Trap might morph proxy.
MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler(
- String* name_raw, DeleteMode mode) {
+ Name* name_raw, DeleteMode mode) {
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
Handle<JSProxy> receiver(this);
MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
JSReceiver* receiver_raw,
- String* name_raw) {
+ Name* name_raw) {
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
Handle<JSProxy> proxy(this);
MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
- String* name_raw,
+ Name* name_raw,
Object* value_raw,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
// Optimization for 2-byte strings often used as keys in a decompression
// dictionary. We internalize these short keys to avoid constantly
// reallocating them.
- if (!name_raw->IsInternalizedString() && name_raw->length() <= 2) {
+ if (name_raw->IsString() && !name_raw->IsInternalizedString() &&
+ String::cast(name_raw)->length() <= 2) {
Object* internalized_version;
- { MaybeObject* maybe_string_version = heap->InternalizeString(name_raw);
+ { MaybeObject* maybe_string_version =
+ heap->InternalizeString(String::cast(name_raw));
if (maybe_string_version->ToObject(&internalized_version)) {
name_raw = String::cast(internalized_version);
}
// SetPropertyViaPrototypes might call back into JavaScript.
HandleScope scope(isolate);
Handle<JSObject> self(this);
- Handle<String> name(name_raw);
+ Handle<Name> name(name_raw);
Handle<Object> value(value_raw, isolate);
if (!lookup->IsProperty() && !self->IsJSContextExtensionObject()) {
// doesn't handle function prototypes correctly.
Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
Handle<JSObject> object,
- Handle<String> key,
+ Handle<Name> key,
Handle<Object> value,
PropertyAttributes attributes) {
CALL_HEAP_FUNCTION(
MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
- String* name_raw,
+ Name* name_raw,
Object* value_raw,
PropertyAttributes attributes) {
// Make sure that the top context does not change when doing callbacks or
// From this point on everything needs to be handlified.
HandleScope scope(isolate);
Handle<JSObject> self(this);
- Handle<String> name(name_raw);
+ Handle<Name> name(name_raw);
Handle<Object> value(value_raw, isolate);
Handle<Object> old_value(isolate->heap()->the_hole_value(), isolate);
PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
JSObject* receiver,
- String* name,
+ Name* name,
bool continue_search) {
// Check local property, ignore interceptor.
LookupResult result(GetIsolate());
PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
JSObject* receiver,
- String* name,
+ Name* name,
bool continue_search) {
+ // TODO(rossberg): Support symbols in the API.
+ if (name->IsSymbol()) return ABSENT;
+
Isolate* isolate = GetIsolate();
// Make sure that the top context does not change when doing
Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
Handle<JSObject> receiver_handle(receiver);
Handle<JSObject> holder_handle(this);
- Handle<String> name_handle(name);
+ Handle<String> name_handle(String::cast(name));
CustomArguments args(isolate, interceptor->data(), receiver, this);
v8::AccessorInfo info(args.end());
if (!interceptor->query()->IsUndefined()) {
PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
JSReceiver* receiver,
- String* key) {
+ Name* key) {
uint32_t index = 0;
if (IsJSObject() && key->AsArrayIndex(&index)) {
return JSObject::cast(this)->GetElementAttributeWithReceiver(
PropertyAttributes JSReceiver::GetPropertyAttributeForResult(
JSReceiver* receiver,
LookupResult* lookup,
- String* name,
+ Name* name,
bool continue_search) {
// Check access rights if needed.
if (IsAccessCheckNeeded()) {
}
-PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) {
+PropertyAttributes JSReceiver::GetLocalPropertyAttribute(Name* name) {
// Check whether the name is an array index.
uint32_t index = 0;
if (IsJSObject() && name->AsArrayIndex(&index)) {
void JSObject::UpdateMapCodeCache(Handle<JSObject> object,
- Handle<String> name,
+ Handle<Name> name,
Handle<Code> code) {
Isolate* isolate = object->GetIsolate();
CALL_HEAP_FUNCTION_VOID(isolate,
}
-MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) {
+MaybeObject* JSObject::UpdateMapCodeCache(Name* name, Code* code) {
if (map()->is_shared()) {
// Fast case maps are never marked as shared.
ASSERT(!HasFastProperties());
} else {
property_count += 2; // Make space for two more properties.
}
- StringDictionary* dictionary;
- MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count);
+ NameDictionary* dictionary;
+ MaybeObject* maybe_dictionary = NameDictionary::Allocate(property_count);
if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
DescriptorArray* descs = map_of_this->instance_descriptors();
}
-Object* JSObject::GetHiddenProperty(String* key) {
- ASSERT(key->IsInternalizedString());
+Object* JSObject::GetHiddenProperty(Name* key) {
+ ASSERT(key->IsUniqueName());
if (IsJSGlobalProxy()) {
// For a proxy, use the prototype as target object.
Object* proxy_parent = GetPrototype();
Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj,
- Handle<String> key,
+ Handle<Name> key,
Handle<Object> value) {
CALL_HEAP_FUNCTION(obj->GetIsolate(),
obj->SetHiddenProperty(*key, *value),
}
-MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) {
- ASSERT(key->IsInternalizedString());
+MaybeObject* JSObject::SetHiddenProperty(Name* key, Object* value) {
+ ASSERT(key->IsUniqueName());
if (IsJSGlobalProxy()) {
// For a proxy, use the prototype as target object.
Object* proxy_parent = GetPrototype();
}
-void JSObject::DeleteHiddenProperty(String* key) {
- ASSERT(key->IsInternalizedString());
+void JSObject::DeleteHiddenProperty(Name* key) {
+ ASSERT(key->IsUniqueName());
if (IsJSGlobalProxy()) {
// For a proxy, use the prototype as target object.
Object* proxy_parent = GetPrototype();
if (HasFastProperties()) {
// If the object has fast properties, check whether the first slot
// in the descriptor array matches the hidden string. Since the
- // hidden strings hash code is zero (and no other string has hash
+ // hidden strings hash code is zero (and no other name has hash
// code zero) it will always occupy the first entry if present.
DescriptorArray* descriptors = this->map()->instance_descriptors();
if (descriptors->number_of_descriptors() > 0) {
if (HasFastProperties()) {
// If the object has fast properties, check whether the first slot
// in the descriptor array matches the hidden string. Since the
- // hidden strings hash code is zero (and no other string has hash
+ // hidden strings hash code is zero (and no other name has hash
// code zero) it will always occupy the first entry if present.
DescriptorArray* descriptors = this->map()->instance_descriptors();
if (descriptors->number_of_descriptors() > 0) {
}
-MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
+MaybeObject* JSObject::DeletePropertyPostInterceptor(Name* name,
DeleteMode mode) {
// Check local property, ignore interceptor.
LookupResult result(GetIsolate());
}
-MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) {
+MaybeObject* JSObject::DeletePropertyWithInterceptor(Name* name) {
+ // TODO(rossberg): Support symbols in the API.
+ if (name->IsSymbol()) return GetHeap()->false_value();
+
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
- Handle<String> name_handle(name);
+ Handle<String> name_handle(String::cast(name));
Handle<JSObject> this_handle(this);
if (!interceptor->deleter()->IsUndefined()) {
v8::NamedPropertyDeleter deleter =
Handle<Object> JSObject::DeleteProperty(Handle<JSObject> obj,
- Handle<String> prop) {
+ Handle<Name> prop) {
CALL_HEAP_FUNCTION(obj->GetIsolate(),
obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION),
Object);
}
-MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
+MaybeObject* JSObject::DeleteProperty(Name* name, DeleteMode mode) {
Isolate* isolate = GetIsolate();
// ECMA-262, 3rd, 8.6.2.5
- ASSERT(name->IsString());
+ ASSERT(name->IsName());
// Check access rights if needed.
if (IsAccessCheckNeeded() &&
// From this point on everything needs to be handlified.
HandleScope scope(isolate);
Handle<JSObject> self(this);
- Handle<String> hname(name);
+ Handle<Name> hname(name);
Handle<Object> old_value = isolate->factory()->the_hole_value();
bool is_observed = FLAG_harmony_observation && self->map()->is_observed();
}
-MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
+MaybeObject* JSReceiver::DeleteProperty(Name* name, DeleteMode mode) {
if (IsJSProxy()) {
return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
}
}
-int Map::PropertyIndexFor(String* name) {
+int Map::PropertyIndexFor(Name* name) {
DescriptorArray* descs = instance_descriptors();
int limit = NumberOfOwnDescriptors();
for (int i = 0; i < limit; i++) {
}
-AccessorDescriptor* Map::FindAccessor(String* name) {
+AccessorDescriptor* Map::FindAccessor(Name* name) {
DescriptorArray* descs = instance_descriptors();
int number_of_own_descriptors = NumberOfOwnDescriptors();
for (int i = 0; i < number_of_own_descriptors; i++) {
void JSReceiver::LocalLookup(
- String* name, LookupResult* result, bool search_hidden_prototypes) {
- ASSERT(name->IsString());
+ Name* name, LookupResult* result, bool search_hidden_prototypes) {
+ ASSERT(name->IsName());
Heap* heap = GetHeap();
}
-void JSReceiver::Lookup(String* name, LookupResult* result) {
+void JSReceiver::Lookup(Name* name, LookupResult* result) {
// Ecma-262 3rd 8.6.2.4
Heap* heap = GetHeap();
for (Object* current = this;
// Search object and its prototype chain for callback properties.
-void JSObject::LookupCallbackProperty(String* name, LookupResult* result) {
+void JSObject::LookupCallbackProperty(Name* name, LookupResult* result) {
Heap* heap = GetHeap();
for (Object* current = this;
current != heap->null_value() && current->IsJSObject();
}
-MaybeObject* JSObject::CreateAccessorPairFor(String* name) {
+MaybeObject* JSObject::CreateAccessorPairFor(Name* name) {
LookupResult result(GetHeap()->isolate());
LocalLookupRealNamedProperty(name, &result);
if (result.IsPropertyCallbacks()) {
}
-MaybeObject* JSObject::DefinePropertyAccessor(String* name,
+MaybeObject* JSObject::DefinePropertyAccessor(Name* name,
Object* getter,
Object* setter,
PropertyAttributes attributes) {
}
-bool JSObject::CanSetCallback(String* name) {
+bool JSObject::CanSetCallback(Name* name) {
ASSERT(!IsAccessCheckNeeded() ||
GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
}
-MaybeObject* JSObject::SetPropertyCallback(String* name,
+MaybeObject* JSObject::SetPropertyCallback(Name* name,
Object* structure,
PropertyAttributes attributes) {
// Normalize object to make this operation simple.
void JSObject::DefineAccessor(Handle<JSObject> object,
- Handle<String> name,
+ Handle<Name> name,
Handle<Object> getter,
Handle<Object> setter,
PropertyAttributes attributes) {
object->DefineAccessor(*name, *getter, *setter, attributes));
}
-MaybeObject* JSObject::DefineAccessor(String* name_raw,
+MaybeObject* JSObject::DefineAccessor(Name* name_raw,
Object* getter_raw,
Object* setter_raw,
PropertyAttributes attributes) {
AssertNoContextChange ncc;
// Try to flatten before operating on the string.
- name_raw->TryFlatten();
+ if (name_raw->IsString()) String::cast(name_raw)->TryFlatten();
if (!CanSetCallback(name_raw)) return isolate->heap()->undefined_value();
// From this point on everything needs to be handlified.
HandleScope scope(isolate);
Handle<JSObject> self(this);
- Handle<String> name(name_raw);
+ Handle<Name> name(name_raw);
Handle<Object> getter(getter_raw, isolate);
Handle<Object> setter(setter_raw, isolate);
}
-MaybeObject* JSObject::DefineFastAccessor(String* name,
+MaybeObject* JSObject::DefineFastAccessor(Name* name,
AccessorComponent component,
Object* accessor,
PropertyAttributes attributes) {
MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
Isolate* isolate = GetIsolate();
- String* name = String::cast(info->name());
+ Name* name = Name::cast(info->name());
// Check access rights if needed.
if (IsAccessCheckNeeded() &&
!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
AssertNoContextChange ncc;
// Try to flatten before operating on the string.
- name->TryFlatten();
+ if (name->IsString()) String::cast(name)->TryFlatten();
if (!CanSetCallback(name)) return isolate->heap()->undefined_value();
}
-Object* JSObject::LookupAccessor(String* name, AccessorComponent component) {
+Object* JSObject::LookupAccessor(Name* name, AccessorComponent component) {
Heap* heap = GetHeap();
// Make sure that the top context does not change when doing callbacks or
MaybeObject* maybe_result = CopyDropDescriptors();
if (!maybe_result->To(&result)) return maybe_result;
- String* name = descriptor->GetKey();
+ Name* name = descriptor->GetKey();
TransitionArray* transitions;
MaybeObject* maybe_transitions =
MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
- String* name,
+ Name* name,
TransitionFlag flag,
int descriptor_index) {
ASSERT(descriptors->IsSortedNoDuplicates());
TransitionFlag flag) {
DescriptorArray* descriptors = instance_descriptors();
- // Ensure the key is an internalized string.
- MaybeObject* maybe_failure = descriptor->KeyToInternalizedString();
+ // Ensure the key is unique.
+ MaybeObject* maybe_failure = descriptor->KeyToUniqueName();
if (maybe_failure->IsFailure()) return maybe_failure;
int old_size = NumberOfOwnDescriptors();
new_descriptors->Append(descriptor, witness);
}
- String* key = descriptor->GetKey();
+ Name* key = descriptor->GetKey();
int insertion_index = new_descriptors->number_of_descriptors() - 1;
return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index);
TransitionFlag flag) {
DescriptorArray* old_descriptors = instance_descriptors();
- // Ensure the key is an internalized string.
- MaybeObject* maybe_result = descriptor->KeyToInternalizedString();
+ // Ensure the key is unique.
+ MaybeObject* maybe_result = descriptor->KeyToUniqueName();
if (maybe_result->IsFailure()) return maybe_result;
// We replace the key if it is already present.
Descriptor* descriptor,
int insertion_index,
TransitionFlag flag) {
- // Ensure the key is an internalized string.
- MaybeObject* maybe_failure = descriptor->KeyToInternalizedString();
+ // Ensure the key is unique.
+ MaybeObject* maybe_failure = descriptor->KeyToUniqueName();
if (maybe_failure->IsFailure()) return maybe_failure;
- String* key = descriptor->GetKey();
+ Name* key = descriptor->GetKey();
ASSERT(key == descriptors->GetKey(insertion_index));
int new_size = NumberOfOwnDescriptors();
void Map::UpdateCodeCache(Handle<Map> map,
- Handle<String> name,
+ Handle<Name> name,
Handle<Code> code) {
Isolate* isolate = map->GetIsolate();
CALL_HEAP_FUNCTION_VOID(isolate,
}
-MaybeObject* Map::UpdateCodeCache(String* name, Code* code) {
+MaybeObject* Map::UpdateCodeCache(Name* name, Code* code) {
ASSERT(!is_shared() || code->allowed_in_shared_map_code_cache());
// Allocate the code cache if not present.
}
-Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
+Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
// Do a lookup if a code cache exists.
if (!code_cache()->IsFixedArray()) {
return CodeCache::cast(code_cache())->Lookup(name, flags);
}
-void Map::RemoveFromCodeCache(String* name, Code* code, int index) {
+void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
// No GC is supposed to happen between a call to IndexInCodeCache and
// RemoveFromCodeCache so the code cache must be there.
ASSERT(!code_cache()->IsFixedArray());
}
-MaybeObject* CodeCache::Update(String* name, Code* code) {
+MaybeObject* CodeCache::Update(Name* name, Code* code) {
// The number of monomorphic stubs for normal load/store/call IC's can grow to
// a large number and therefore they need to go into a hash table. They are
// used to load global properties from cells.
}
-MaybeObject* CodeCache::UpdateDefaultCache(String* name, Code* code) {
+MaybeObject* CodeCache::UpdateDefaultCache(Name* name, Code* code) {
// When updating the default code cache we disregard the type encoded in the
// flags. This allows call constant stubs to overwrite call field
// stubs, etc.
cache->set(i + kCodeCacheEntryCodeOffset, code);
return this;
}
- if (name->Equals(String::cast(key))) {
+ if (name->Equals(Name::cast(key))) {
Code::Flags found =
Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
if (Code::RemoveTypeFromFlags(found) == flags) {
}
-MaybeObject* CodeCache::UpdateNormalTypeCache(String* name, Code* code) {
+MaybeObject* CodeCache::UpdateNormalTypeCache(Name* name, Code* code) {
// Adding a new entry can cause a new cache to be allocated.
CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
Object* new_cache;
}
-Object* CodeCache::Lookup(String* name, Code::Flags flags) {
+Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
if (Code::ExtractTypeFromFlags(flags) == Code::NORMAL) {
return LookupNormalTypeCache(name, flags);
} else {
}
-Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) {
+Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
FixedArray* cache = default_cache();
int length = cache->length();
for (int i = 0; i < length; i += kCodeCacheEntrySize) {
// Skip deleted elements.
if (key->IsNull()) continue;
if (key->IsUndefined()) return key;
- if (name->Equals(String::cast(key))) {
+ if (name->Equals(Name::cast(key))) {
Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
if (code->flags() == flags) {
return code;
}
-Object* CodeCache::LookupNormalTypeCache(String* name, Code::Flags flags) {
+Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
if (!normal_type_cache()->IsUndefined()) {
CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
return cache->Lookup(name, flags);
if (code->type() == Code::NORMAL) {
if (normal_type_cache()->IsUndefined()) return -1;
CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
- return cache->GetIndex(String::cast(name), code->flags());
+ return cache->GetIndex(Name::cast(name), code->flags());
}
FixedArray* array = default_cache();
if (code->type() == Code::NORMAL) {
ASSERT(!normal_type_cache()->IsUndefined());
CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
- ASSERT(cache->GetIndex(String::cast(name), code->flags()) == index);
+ ASSERT(cache->GetIndex(Name::cast(name), code->flags()) == index);
cache->RemoveByIndex(index);
} else {
FixedArray* array = default_cache();
// lookup not to create a new entry.
class CodeCacheHashTableKey : public HashTableKey {
public:
- CodeCacheHashTableKey(String* name, Code::Flags flags)
+ CodeCacheHashTableKey(Name* name, Code::Flags flags)
: name_(name), flags_(flags), code_(NULL) { }
- CodeCacheHashTableKey(String* name, Code* code)
+ CodeCacheHashTableKey(Name* name, Code* code)
: name_(name),
flags_(code->flags()),
code_(code) { }
bool IsMatch(Object* other) {
if (!other->IsFixedArray()) return false;
FixedArray* pair = FixedArray::cast(other);
- String* name = String::cast(pair->get(0));
+ Name* name = Name::cast(pair->get(0));
Code::Flags flags = Code::cast(pair->get(1))->flags();
if (flags != flags_) {
return false;
return name_->Equals(name);
}
- static uint32_t NameFlagsHashHelper(String* name, Code::Flags flags) {
+ static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
return name->Hash() ^ flags;
}
uint32_t HashForObject(Object* obj) {
FixedArray* pair = FixedArray::cast(obj);
- String* name = String::cast(pair->get(0));
+ Name* name = Name::cast(pair->get(0));
Code* code = Code::cast(pair->get(1));
return NameFlagsHashHelper(name, code->flags());
}
}
private:
- String* name_;
+ Name* name_;
Code::Flags flags_;
// TODO(jkummerow): We should be able to get by without this.
Code* code_;
};
-Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) {
+Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
CodeCacheHashTableKey key(name, flags);
int entry = FindEntry(&key);
if (entry == kNotFound) return GetHeap()->undefined_value();
}
-MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) {
+MaybeObject* CodeCacheHashTable::Put(Name* name, Code* code) {
CodeCacheHashTableKey key(name, code);
Object* obj;
{ MaybeObject* maybe_obj = EnsureCapacity(1, &key);
}
-int CodeCacheHashTable::GetIndex(String* name, Code::Flags flags) {
+int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
CodeCacheHashTableKey key(name, flags);
int entry = FindEntry(&key);
return (entry == kNotFound) ? -1 : entry;
if (FLAG_enable_slow_asserts) {
for (int i = 0; i < result->length(); i++) {
Object* current = result->get(i);
- ASSERT(current->IsNumber() || current->IsString());
+ ASSERT(current->IsNumber() || current->IsName());
}
}
#endif
if (FLAG_enable_slow_asserts) {
for (int i = 0; i < result->length(); i++) {
Object* current = result->get(i);
- ASSERT(current->IsNumber() || current->IsString());
+ ASSERT(current->IsNumber() || current->IsName());
}
}
#endif
}
} else {
if (i != transition_index) {
- String* key = t->GetKey(i);
+ Name* key = t->GetKey(i);
t->SetKey(transition_index, key);
Object** key_slot = t->GetKeySlot(transition_index);
collector->RecordSlot(key_slot, key_slot, key);
}
-PropertyType JSObject::GetLocalPropertyType(String* name) {
+PropertyType JSObject::GetLocalPropertyType(Name* name) {
uint32_t index = 0;
if (name->AsArrayIndex(&index)) {
return GetLocalElementType(index);
}
-AccessorPair* JSObject::GetLocalPropertyAccessorPair(String* name) {
+AccessorPair* JSObject::GetLocalPropertyAccessorPair(Name* name) {
uint32_t index = 0;
if (name->AsArrayIndex(&index)) {
return GetLocalElementAccessorPair(index);
MaybeObject* JSObject::GetPropertyPostInterceptor(
Object* receiver,
- String* name,
+ Name* name,
PropertyAttributes* attributes) {
// Check local property in holder, ignore interceptor.
LookupResult result(GetIsolate());
MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
Object* receiver,
- String* name,
+ Name* name,
PropertyAttributes* attributes) {
// Check local property in holder, ignore interceptor.
LookupResult result(GetIsolate());
MaybeObject* JSObject::GetPropertyWithInterceptor(
Object* receiver,
- String* name,
+ Name* name,
PropertyAttributes* attributes) {
+ // TODO(rossberg): Support symbols in the API.
+ if (name->IsSymbol()) return GetHeap()->undefined_value();
+
Isolate* isolate = GetIsolate();
InterceptorInfo* interceptor = GetNamedInterceptor();
HandleScope scope(isolate);
Handle<Object> receiver_handle(receiver, isolate);
Handle<JSObject> holder_handle(this);
- Handle<String> name_handle(name);
+ Handle<String> name_handle(String::cast(name));
if (!interceptor->getter()->IsUndefined()) {
v8::NamedPropertyGetter getter =
}
-bool JSObject::HasRealNamedProperty(String* key) {
+bool JSObject::HasRealNamedProperty(Name* key) {
// Check access rights if needed.
Isolate* isolate = GetIsolate();
if (IsAccessCheckNeeded()) {
}
-bool JSObject::HasRealNamedCallbackProperty(String* key) {
+bool JSObject::HasRealNamedCallbackProperty(Name* key) {
// Check access rights if needed.
Isolate* isolate = GetIsolate();
if (IsAccessCheckNeeded()) {
} else {
property_dictionary()->CopyKeysTo(storage,
index,
- StringDictionary::UNSORTED);
+ NameDictionary::UNSORTED);
}
}
// Find entry for key otherwise return kNotFound.
-int StringDictionary::FindEntry(String* key) {
- if (!key->IsInternalizedString()) {
- return HashTable<StringDictionaryShape, String*>::FindEntry(key);
+int NameDictionary::FindEntry(Name* key) {
+ if (!key->IsUniqueName()) {
+ return HashTable<NameDictionaryShape, Name*>::FindEntry(key);
}
- // Optimized for internalized string key. Knowledge of the key type allows:
- // 1. Move the check if the key is internalized out of the loop.
- // 2. Avoid comparing hash codes in internalized-to-internalized comparison.
- // 3. Detect a case when a dictionary key is not internalized but the key is.
+ // Optimized for unique names. Knowledge of the key type allows:
+ // 1. Move the check if the key is unique out of the loop.
+ // 2. Avoid comparing hash codes in unique-to-unique comparison.
+ // 3. Detect a case when a dictionary key is not unique but the key is.
// In case of positive result the dictionary key may be replaced by the
// internalized string with minimal performance penalty. It gives a chance
// to perform further lookups in code stubs (and significant performance
Object* element = get(index);
if (element->IsUndefined()) break; // Empty entry.
if (key == element) return entry;
- if (!element->IsInternalizedString() &&
+ if (!element->IsUniqueName() &&
!element->IsTheHole() &&
- String::cast(element)->Equals(key)) {
- // Replace a key that is not an internalized string by the equivalent
+ Name::cast(element)->Equals(key)) {
+ // Replace a key that is a non-internalized string by the equivalent
// internalized string for faster further lookups.
set(index, key);
return entry;
}
- ASSERT(element->IsTheHole() || !String::cast(element)->Equals(key));
+ ASSERT(element->IsTheHole() || !Name::cast(element)->Equals(key));
entry = NextProbe(entry, count++, capacity);
}
return kNotFound;
template class HashTable<ObjectHashTableShape<2>, Object*>;
-template class Dictionary<StringDictionaryShape, String*>;
+template class Dictionary<NameDictionaryShape, Name*>;
template class Dictionary<SeededNumberDictionaryShape, uint32_t>;
template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
Allocate(int at_least_space_for);
-template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate(
- int);
+template MaybeObject* Dictionary<NameDictionaryShape, Name*>::Allocate(int n);
template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut(
uint32_t, Object*);
template Object* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
SlowReverseLookup(Object* value);
-template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup(
+template Object* Dictionary<NameDictionaryShape, Name*>::SlowReverseLookup(
Object*);
template void Dictionary<SeededNumberDictionaryShape, uint32_t>::CopyKeysTo(
PropertyAttributes,
Dictionary<SeededNumberDictionaryShape, uint32_t>::SortMode);
-template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty(
+template Object* Dictionary<NameDictionaryShape, Name*>::DeleteProperty(
int, JSObject::DeleteMode);
template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>::
DeleteProperty(int, JSObject::DeleteMode);
-template MaybeObject* Dictionary<StringDictionaryShape, String*>::Shrink(
- String*);
+template MaybeObject* Dictionary<NameDictionaryShape, Name*>::Shrink(Name* n);
template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Shrink(
uint32_t);
-template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo(
+template void Dictionary<NameDictionaryShape, Name*>::CopyKeysTo(
FixedArray*,
int,
- Dictionary<StringDictionaryShape, String*>::SortMode);
+ Dictionary<NameDictionaryShape, Name*>::SortMode);
template int
-Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes(
+Dictionary<NameDictionaryShape, Name*>::NumberOfElementsFilterAttributes(
PropertyAttributes);
-template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add(
- String*, Object*, PropertyDetails);
+template MaybeObject* Dictionary<NameDictionaryShape, Name*>::Add(
+ Name*, Object*, PropertyDetails);
template MaybeObject*
-Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices();
+Dictionary<NameDictionaryShape, Name*>::GenerateNewEnumerationIndices();
template int
Dictionary<SeededNumberDictionaryShape, uint32_t>::
template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
EnsureCapacity(int, uint32_t);
-template MaybeObject* Dictionary<StringDictionaryShape, String*>::
- EnsureCapacity(int, String*);
+template MaybeObject* Dictionary<NameDictionaryShape, Name*>::
+ EnsureCapacity(int, Name*);
template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
-template MaybeObject* Dictionary<StringDictionaryShape, String*>::AddEntry(
- String*, Object*, PropertyDetails, uint32_t);
+template MaybeObject* Dictionary<NameDictionaryShape, Name*>::AddEntry(
+ Name*, Object*, PropertyDetails, uint32_t);
template
int Dictionary<SeededNumberDictionaryShape, uint32_t>::NumberOfEnumElements();
template
-int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements();
+int Dictionary<NameDictionaryShape, Name*>::NumberOfEnumElements();
template
int HashTable<SeededNumberDictionaryShape, uint32_t>::FindEntry(uint32_t);
Handle<JSGlobalPropertyCell> GlobalObject::EnsurePropertyCell(
Handle<GlobalObject> global,
- Handle<String> name) {
+ Handle<Name> name) {
Isolate* isolate = global->GetIsolate();
CALL_HEAP_FUNCTION(isolate,
global->EnsurePropertyCell(*name),
}
-MaybeObject* GlobalObject::EnsurePropertyCell(String* name) {
+MaybeObject* GlobalObject::EnsurePropertyCell(Name* name) {
ASSERT(!HasFastProperties());
int entry = property_dictionary()->FindEntry(name);
- if (entry == StringDictionary::kNotFound) {
+ if (entry == NameDictionary::kNotFound) {
Heap* heap = GetHeap();
Object* cell;
{ MaybeObject* maybe_cell =
property_dictionary()->Add(name, cell, details);
if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary;
}
- set_properties(StringDictionary::cast(dictionary));
+ set_properties(NameDictionary::cast(dictionary));
return cell;
} else {
Object* value = property_dictionary()->ValueAt(entry);
}
-// StringsKey used for HashTable where key is array of internalzied strings.
+// StringsKey used for HashTable where key is array of internalized strings.
class StringsKey : public HashTableKey {
public:
explicit StringsKey(FixedArray* strings) : strings_(strings) { }
}
-void StringDictionary::DoGenerateNewEnumerationIndices(
- Handle<StringDictionary> dictionary) {
+void NameDictionary::DoGenerateNewEnumerationIndices(
+ Handle<NameDictionary> dictionary) {
CALL_HEAP_FUNCTION_VOID(dictionary->GetIsolate(),
dictionary->GenerateNewEnumerationIndices());
}
SetNextEnumerationIndex(index + 1);
}
SetEntry(entry, k, value, details);
- ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
- || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
+ ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() ||
+ Dictionary<Shape, Key>::KeyAt(entry)->IsName()));
HashTable<Shape, Key>::ElementAdded();
return this;
}
}
-FixedArray* StringDictionary::CopyEnumKeysTo(FixedArray* storage) {
+FixedArray* NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
int length = storage->length();
ASSERT(length >= NumberOfEnumElements());
Heap* heap = GetHeap();
}
-MaybeObject* StringDictionary::TransformPropertiesToFastFor(
+MaybeObject* NameDictionary::TransformPropertiesToFastFor(
JSObject* obj, int unused_property_fields) {
// Make sure we preserve dictionary representation if there are too many
// descriptors.
Object* k = KeyAt(i);
if (IsKey(k)) {
Object* value = ValueAt(i);
- // Ensure the key is an internalized string before writing into the
- // instance descriptor.
- String* key;
- MaybeObject* maybe_key = heap->InternalizeString(String::cast(k));
- if (!maybe_key->To(&key)) return maybe_key;
+ Name* key;
+ if (k->IsSymbol()) {
+ key = Symbol::cast(k);
+ } else {
+ // Ensure the key is a unique name before writing into the
+ // instance descriptor.
+ MaybeObject* maybe_key = heap->InternalizeString(String::cast(k));
+ if (!maybe_key->To(&key)) return maybe_key;
+ }
PropertyDetails details = DetailsAt(i);
ASSERT(details.descriptor_index() == details.dictionary_index());
V(ObjectHashTable) \
-class JSReceiver;
-
// Object is the abstract superclass for all classes in the
// object hierarchy.
// Object does not use any virtual functions to avoid the
// Failure is returned otherwise.
MUST_USE_RESULT inline MaybeObject* ToSmi();
- void Lookup(String* name, LookupResult* result);
+ void Lookup(Name* name, LookupResult* result);
// Property access.
- MUST_USE_RESULT inline MaybeObject* GetProperty(String* key);
+ MUST_USE_RESULT inline MaybeObject* GetProperty(Name* key);
MUST_USE_RESULT inline MaybeObject* GetProperty(
- String* key,
+ Name* key,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetPropertyWithReceiver(
Object* receiver,
- String* key,
+ Name* key,
PropertyAttributes* attributes);
- static Handle<Object> GetProperty(Handle<Object> object, Handle<String> key);
+ static Handle<Object> GetProperty(Handle<Object> object, Handle<Name> key);
static Handle<Object> GetProperty(Handle<Object> object,
Handle<Object> receiver,
LookupResult* result,
- Handle<String> key,
+ Handle<Name> key,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetProperty(Object* receiver,
LookupResult* result,
- String* key,
+ Name* key,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
static inline JSReceiver* cast(Object* obj);
static Handle<Object> SetProperty(Handle<JSReceiver> object,
- Handle<String> key,
+ Handle<Name> key,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode);
// Can cause GC.
MUST_USE_RESULT MaybeObject* SetProperty(
- String* key,
+ Name* key,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
StoreFromKeyed store_from_keyed = MAY_BE_STORE_FROM_KEYED);
MUST_USE_RESULT MaybeObject* SetProperty(
LookupResult* result,
- String* key,
+ Name* key,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSReceiver* setter,
Object* value);
- MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
+ MUST_USE_RESULT MaybeObject* DeleteProperty(Name* name, DeleteMode mode);
MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
// Set the index'th array element.
// function that was used to instantiate the object).
String* constructor_name();
- inline PropertyAttributes GetPropertyAttribute(String* name);
+ inline PropertyAttributes GetPropertyAttribute(Name* name);
PropertyAttributes GetPropertyAttributeWithReceiver(JSReceiver* receiver,
- String* name);
- PropertyAttributes GetLocalPropertyAttribute(String* name);
+ Name* name);
+ PropertyAttributes GetLocalPropertyAttribute(Name* name);
inline PropertyAttributes GetElementAttribute(uint32_t index);
inline PropertyAttributes GetLocalElementAttribute(uint32_t index);
// Can cause a GC.
- inline bool HasProperty(String* name);
- inline bool HasLocalProperty(String* name);
+ inline bool HasProperty(Name* name);
+ inline bool HasLocalProperty(Name* name);
inline bool HasElement(uint32_t index);
inline bool HasLocalElement(uint32_t index);
// Lookup a property. If found, the result is valid and has
// detailed information.
- void LocalLookup(String* name, LookupResult* result,
+ void LocalLookup(Name* name, LookupResult* result,
bool search_hidden_prototypes = false);
- void Lookup(String* name, LookupResult* result);
+ void Lookup(Name* name, LookupResult* result);
protected:
Smi* GenerateIdentityHash();
private:
PropertyAttributes GetPropertyAttributeForResult(JSReceiver* receiver,
LookupResult* result,
- String* name,
+ Name* name,
bool continue_search);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver);
DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties.
inline void initialize_properties();
inline bool HasFastProperties();
- inline StringDictionary* property_dictionary(); // Gets slow properties.
+ inline NameDictionary* property_dictionary(); // Gets slow properties.
// [elements]: The elements (properties with names that are integers).
//
MUST_USE_RESULT MaybeObject* GetPropertyWithCallback(Object* receiver,
Object* structure,
- String* name);
+ Name* name);
// Can cause GC.
MUST_USE_RESULT MaybeObject* SetPropertyForResult(LookupResult* result,
- String* key,
+ Name* key,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
StoreFromKeyed store_mode);
MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
LookupResult* result,
- String* name,
+ Name* name,
Object* value,
bool check_prototype,
StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* SetPropertyWithCallback(
Object* structure,
- String* name,
+ Name* name,
Object* value,
JSObject* holder,
StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor(
- String* name,
+ Name* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor(
- String* name,
+ Name* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
static Handle<Object> SetLocalPropertyIgnoreAttributes(
Handle<JSObject> object,
- Handle<String> key,
+ Handle<Name> key,
Handle<Object> value,
PropertyAttributes attributes);
// Try to follow an existing transition to a field with attributes NONE. The
// return value indicates whether the transition was successful.
static inline bool TryTransitionToField(Handle<JSObject> object,
- Handle<String> key);
+ Handle<Name> key);
inline int LastAddedFieldIndex();
// Can cause GC.
MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes(
- String* key,
+ Name* key,
Object* value,
PropertyAttributes attributes);
// Sets the property value in a normalized object given (key, value, details).
// Handles the special representation of JS global objects.
static Handle<Object> SetNormalizedProperty(Handle<JSObject> object,
- Handle<String> key,
+ Handle<Name> key,
Handle<Object> value,
PropertyDetails details);
- MUST_USE_RESULT MaybeObject* SetNormalizedProperty(String* name,
+ MUST_USE_RESULT MaybeObject* SetNormalizedProperty(Name* name,
Object* value,
PropertyDetails details);
// Deletes the named property in a normalized object.
- MUST_USE_RESULT MaybeObject* DeleteNormalizedProperty(String* name,
+ MUST_USE_RESULT MaybeObject* DeleteNormalizedProperty(Name* name,
DeleteMode mode);
MUST_USE_RESULT MaybeObject* OptimizeAsPrototype();
// Used from JSReceiver.
PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver,
- String* name,
+ Name* name,
bool continue_search);
PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject* receiver,
- String* name,
+ Name* name,
bool continue_search);
PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(
Object* receiver,
LookupResult* result,
- String* name,
+ Name* name,
bool continue_search);
PropertyAttributes GetElementAttributeWithReceiver(JSReceiver* receiver,
uint32_t index,
bool continue_search);
static void DefineAccessor(Handle<JSObject> object,
- Handle<String> name,
+ Handle<Name> name,
Handle<Object> getter,
Handle<Object> setter,
PropertyAttributes attributes);
// Can cause GC.
- MUST_USE_RESULT MaybeObject* DefineAccessor(String* name,
+ MUST_USE_RESULT MaybeObject* DefineAccessor(Name* name,
Object* getter,
Object* setter,
PropertyAttributes attributes);
// Returns a JavaScript null if this was not possible and we have to use the
// slow case. Note that we can fail due to allocations, too.
MUST_USE_RESULT MaybeObject* DefineFastAccessor(
- String* name,
+ Name* name,
AccessorComponent component,
Object* accessor,
PropertyAttributes attributes);
- Object* LookupAccessor(String* name, AccessorComponent component);
+ Object* LookupAccessor(Name* name, AccessorComponent component);
MUST_USE_RESULT MaybeObject* DefineAccessor(AccessorInfo* info);
MUST_USE_RESULT MaybeObject* GetPropertyWithFailedAccessCheck(
Object* receiver,
LookupResult* result,
- String* name,
+ Name* name,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetPropertyWithInterceptor(
Object* receiver,
- String* name,
+ Name* name,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetPropertyPostInterceptor(
Object* receiver,
- String* name,
+ Name* name,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetLocalPropertyPostInterceptor(
Object* receiver,
- String* name,
+ Name* name,
PropertyAttributes* attributes);
// Returns true if this is an instance of an api function and has
// Sets a hidden property on this object. Returns this object if successful,
// undefined if called on a detached proxy.
static Handle<Object> SetHiddenProperty(Handle<JSObject> obj,
- Handle<String> key,
+ Handle<Name> key,
Handle<Object> value);
// Returns a failure if a GC is required.
- MUST_USE_RESULT MaybeObject* SetHiddenProperty(String* key, Object* value);
+ MUST_USE_RESULT MaybeObject* SetHiddenProperty(Name* key, Object* value);
// Gets the value of a hidden property with the given key. Returns undefined
// if the property doesn't exist (or if called on a detached proxy),
// otherwise returns the value set for the key.
- Object* GetHiddenProperty(String* key);
+ Object* GetHiddenProperty(Name* key);
// Deletes a hidden property. Deleting a non-existing property is
// considered successful.
- void DeleteHiddenProperty(String* key);
+ void DeleteHiddenProperty(Name* key);
// Returns true if the object has a property with the hidden string as name.
bool HasHiddenProperties();
MUST_USE_RESULT MaybeObject* SetIdentityHash(Smi* hash, CreationFlag flag);
static Handle<Object> DeleteProperty(Handle<JSObject> obj,
- Handle<String> name);
+ Handle<Name> name);
// Can cause GC.
- MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
+ MUST_USE_RESULT MaybeObject* DeleteProperty(Name* name, DeleteMode mode);
static Handle<Object> DeleteElement(Handle<JSObject> obj, uint32_t index);
MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
return old_capacity + (old_capacity >> 1) + 16;
}
- PropertyType GetLocalPropertyType(String* name);
+ PropertyType GetLocalPropertyType(Name* name);
PropertyType GetLocalElementType(uint32_t index);
// These methods do not perform access checks!
- AccessorPair* GetLocalPropertyAccessorPair(String* name);
+ AccessorPair* GetLocalPropertyAccessorPair(Name* name);
AccessorPair* GetLocalElementAccessorPair(uint32_t index);
MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
inline bool HasIndexedInterceptor();
// Support functions for v8 api (needed for correct interceptor behavior).
- bool HasRealNamedProperty(String* key);
+ bool HasRealNamedProperty(Name* key);
bool HasRealElementProperty(uint32_t index);
- bool HasRealNamedCallbackProperty(String* key);
+ bool HasRealNamedCallbackProperty(Name* key);
// Get the header size for a JSObject. Used to compute the index of
// internal fields as well as the number of internal fields.
inline void SetInternalField(int index, Smi* value);
// The following lookup functions skip interceptors.
- void LocalLookupRealNamedProperty(String* name, LookupResult* result);
- void LookupRealNamedProperty(String* name, LookupResult* result);
- void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
+ void LocalLookupRealNamedProperty(Name* name, LookupResult* result);
+ void LookupRealNamedProperty(Name* name, LookupResult* result);
+ void LookupRealNamedPropertyInPrototypes(Name* name, LookupResult* result);
MUST_USE_RESULT MaybeObject* SetElementWithCallbackSetterInPrototypes(
uint32_t index, Object* value, bool* found, StrictModeFlag strict_mode);
- void LookupCallbackProperty(String* name, LookupResult* result);
+ void LookupCallbackProperty(Name* name, LookupResult* result);
// Returns the number of properties on this object filtering out properties
// with the specified attributes (ignoring interceptors).
// Add a property to a fast-case object using a map transition to
// new_map.
MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* new_map,
- String* name,
+ Name* name,
Object* value,
int field_index);
// This avoids the creation of many maps with the same constant
// function, all orphaned.
MUST_USE_RESULT MaybeObject* AddConstantFunctionProperty(
- String* name,
+ Name* name,
JSFunction* function,
PropertyAttributes attributes);
MUST_USE_RESULT MaybeObject* ReplaceSlowProperty(
- String* name,
+ Name* name,
Object* value,
PropertyAttributes attributes);
// Replaces an existing transition with a transition to a map with a FIELD.
MUST_USE_RESULT MaybeObject* ConvertTransitionToMapTransition(
int transition_index,
- String* name,
+ Name* name,
Object* new_value,
PropertyAttributes attributes);
// Converts a descriptor of any other type to a real field, backed by the
// properties array.
MUST_USE_RESULT MaybeObject* ConvertDescriptorToField(
- String* name,
+ Name* name,
Object* new_value,
PropertyAttributes attributes);
// Add a property to a fast-case object.
MUST_USE_RESULT MaybeObject* AddFastProperty(
- String* name,
+ Name* name,
Object* value,
PropertyAttributes attributes,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
// Add a property to a slow-case object.
- MUST_USE_RESULT MaybeObject* AddSlowProperty(String* name,
+ MUST_USE_RESULT MaybeObject* AddSlowProperty(Name* name,
Object* value,
PropertyAttributes attributes);
// Add a property to an object. May cause GC.
MUST_USE_RESULT MaybeObject* AddProperty(
- String* name,
+ Name* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
MUST_USE_RESULT MaybeObject* NormalizeElements();
static void UpdateMapCodeCache(Handle<JSObject> object,
- Handle<String> name,
+ Handle<Name> name,
Handle<Code> code);
- MUST_USE_RESULT MaybeObject* UpdateMapCodeCache(String* name, Code* code);
+ MUST_USE_RESULT MaybeObject* UpdateMapCodeCache(Name* name, Code* code);
// Transform slow named properties to fast variants.
// Returns failure if allocation failed.
// Enqueue change record for Object.observe. May cause GC.
static void EnqueueChangeRecord(Handle<JSObject> object,
const char* type,
- Handle<String> name,
+ Handle<Name> name,
Handle<Object> old_value);
// Deliver change records to observers. May cause GC.
// read-only, reject and set '*done' to true. Otherwise, set '*done' to
// false. Can cause GC and can return a failure result with '*done==true'.
MUST_USE_RESULT MaybeObject* SetPropertyViaPrototypes(
- String* name,
+ Name* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool* done);
- MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(String* name,
+ MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(Name* name,
DeleteMode mode);
- MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(String* name);
+ MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(Name* name);
MUST_USE_RESULT MaybeObject* DeleteElementWithInterceptor(uint32_t index);
// Gets the current elements capacity and the number of used elements.
void GetElementsCapacityAndUsage(int* capacity, int* used);
- bool CanSetCallback(String* name);
+ bool CanSetCallback(Name* name);
MUST_USE_RESULT MaybeObject* SetElementCallback(
uint32_t index,
Object* structure,
PropertyAttributes attributes);
MUST_USE_RESULT MaybeObject* SetPropertyCallback(
- String* name,
+ Name* name,
Object* structure,
PropertyAttributes attributes);
MUST_USE_RESULT MaybeObject* DefineElementAccessor(
Object* getter,
Object* setter,
PropertyAttributes attributes);
- MUST_USE_RESULT MaybeObject* CreateAccessorPairFor(String* name);
+ MUST_USE_RESULT MaybeObject* CreateAccessorPairFor(Name* name);
MUST_USE_RESULT MaybeObject* DefinePropertyAccessor(
- String* name,
+ Name* name,
Object* getter,
Object* setter,
PropertyAttributes attributes);
Object* new_index_cache);
// Accessors for fetching instance descriptor at descriptor number.
- inline String* GetKey(int descriptor_number);
+ inline Name* GetKey(int descriptor_number);
inline Object** GetKeySlot(int descriptor_number);
inline Object* GetValue(int descriptor_number);
inline Object** GetValueSlot(int descriptor_number);
inline Object* GetCallbacksObject(int descriptor_number);
inline AccessorDescriptor* GetCallbacks(int descriptor_number);
- inline String* GetSortedKey(int descriptor_number);
+ inline Name* GetSortedKey(int descriptor_number);
inline int GetSortedKeyIndex(int descriptor_number);
inline void SetSortedKey(int pointer, int descriptor_number);
void Sort();
// Search the instance descriptors for given name.
- INLINE(int Search(String* name, int number_of_own_descriptors));
+ INLINE(int Search(Name* name, int number_of_own_descriptors));
// As the above, but uses DescriptorLookupCache and updates it when
// necessary.
- INLINE(int SearchWithCache(String* name, Map* map));
+ INLINE(int SearchWithCache(Name* name, Map* map));
// Allocates a DescriptorArray, but returns the singleton
// empty descriptor array object if number_of_descriptors is 0.
enum SearchMode { ALL_ENTRIES, VALID_ENTRIES };
template<SearchMode search_mode, typename T>
-inline int LinearSearch(T* array, String* name, int len, int valid_entries);
+inline int LinearSearch(T* array, Name* name, int len, int valid_entries);
template<SearchMode search_mode, typename T>
-inline int Search(T* array, String* name, int valid_entries = 0);
+inline int Search(T* array, Name* name, int valid_entries = 0);
// HashTable is a subclass of FixedArray that implements a hash table
// MapCache.
//
-// Maps keys that are a fixed array of internalized strings to a map.
+// Maps keys that are a fixed array of unique names to a map.
// Used for canonicalize maps for object literals.
class MapCache: public HashTable<MapCacheShape, HashTableKey*> {
public:
- // Find cached value for a string key, otherwise return null.
+ // Find cached value for a name key, otherwise return null.
Object* Lookup(FixedArray* key);
MUST_USE_RESULT MaybeObject* Put(FixedArray* key, Map* value);
static inline MapCache* cast(Object* obj);
};
-class StringDictionaryShape : public BaseShape<String*> {
+class NameDictionaryShape : public BaseShape<Name*> {
public:
- static inline bool IsMatch(String* key, Object* other);
- static inline uint32_t Hash(String* key);
- static inline uint32_t HashForObject(String* key, Object* object);
- MUST_USE_RESULT static inline MaybeObject* AsObject(String* key);
+ static inline bool IsMatch(Name* key, Object* other);
+ static inline uint32_t Hash(Name* key);
+ static inline uint32_t HashForObject(Name* key, Object* object);
+ MUST_USE_RESULT static inline MaybeObject* AsObject(Name* key);
static const int kPrefixSize = 2;
static const int kEntrySize = 3;
static const bool kIsEnumerable = true;
};
-class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
+class NameDictionary: public Dictionary<NameDictionaryShape, Name*> {
public:
- static inline StringDictionary* cast(Object* obj) {
+ static inline NameDictionary* cast(Object* obj) {
ASSERT(obj->IsDictionary());
- return reinterpret_cast<StringDictionary*>(obj);
+ return reinterpret_cast<NameDictionary*>(obj);
}
// Copies enumerable keys to preallocated fixed array.
FixedArray* CopyEnumKeysTo(FixedArray* storage);
static void DoGenerateNewEnumerationIndices(
- Handle<StringDictionary> dictionary);
+ Handle<NameDictionary> dictionary);
// For transforming properties of a JSObject.
MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor(
// Find entry for key, otherwise return kNotFound. Optimized version of
// HashTable::FindEntry.
- int FindEntry(String* key);
+ int FindEntry(Name* key);
};
Map* transitioned_map);
inline void SetTransition(int transition_index, Map* target);
inline Map* GetTransition(int transition_index);
- MUST_USE_RESULT inline MaybeObject* AddTransition(String* key,
+ MUST_USE_RESULT inline MaybeObject* AddTransition(Name* key,
Map* target,
SimpleTransitionFlag flag);
DECL_ACCESSORS(transitions, TransitionArray)
// with the given holder if the name is found. The holder may be
// NULL when this function is used from the compiler.
inline void LookupDescriptor(JSObject* holder,
- String* name,
+ Name* name,
LookupResult* result);
inline void LookupTransition(JSObject* holder,
- String* name,
+ Name* name,
LookupResult* result);
// The size of transition arrays are limited so they do not end up in large
MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
MUST_USE_RESULT MaybeObject* CopyReplaceDescriptors(
DescriptorArray* descriptors,
- String* name,
+ Name* name,
TransitionFlag flag,
int descriptor_index);
MUST_USE_RESULT MaybeObject* ShareDescriptor(DescriptorArray* descriptors,
MUST_USE_RESULT MaybeObject* Copy();
// Returns the property index for name (only valid for FAST MODE).
- int PropertyIndexFor(String* name);
+ int PropertyIndexFor(Name* name);
// Returns the next free property index (only valid for FAST MODE).
int NextFreePropertyIndex();
static inline Map* cast(Object* obj);
// Locate an accessor in the instance descriptor.
- AccessorDescriptor* FindAccessor(String* name);
+ AccessorDescriptor* FindAccessor(Name* name);
// Code cache operations.
// Update code cache.
static void UpdateCodeCache(Handle<Map> map,
- Handle<String> name,
+ Handle<Name> name,
Handle<Code> code);
- MUST_USE_RESULT MaybeObject* UpdateCodeCache(String* name, Code* code);
+ MUST_USE_RESULT MaybeObject* UpdateCodeCache(Name* name, Code* code);
// Extend the descriptor array of the map with the list of descriptors.
// In case of duplicates, the latest descriptor is used.
static void EnsureDescriptorSlack(Handle<Map> map, int slack);
// Returns the found code or undefined if absent.
- Object* FindInCodeCache(String* name, Code::Flags flags);
+ Object* FindInCodeCache(Name* name, Code::Flags flags);
// Returns the non-negative index of the code object if it is in the
// cache and -1 otherwise.
int IndexInCodeCache(Object* name, Code* code);
// Removes a code object from the code cache at the given index.
- void RemoveFromCodeCache(String* name, Code* code, int index);
+ void RemoveFromCodeCache(Name* name, Code* code, int index);
// Set all map transitions from this map to dead maps to null. Also clear
// back pointers in transition targets so that we do not process this map
// by throwing an exception. This is for the debug and builtins global
// objects, where it is known which properties can be expected to be present
// on the object.
- Object* GetPropertyNoExceptionThrown(String* key) {
+ Object* GetPropertyNoExceptionThrown(Name* key) {
Object* answer = GetProperty(key)->ToObjectUnchecked();
return answer;
}
// Ensure that the global object has a cell for the given property name.
static Handle<JSGlobalPropertyCell> EnsurePropertyCell(
Handle<GlobalObject> global,
- Handle<String> name);
+ Handle<Name> name);
// TODO(kmillikin): This function can be eliminated once the stub cache is
// fully handlified (and the static helper can be written directly).
- MUST_USE_RESULT MaybeObject* EnsurePropertyCell(String* name);
+ MUST_USE_RESULT MaybeObject* EnsurePropertyCell(Name* name);
// Casting.
static inline GlobalObject* cast(Object* obj);
DECL_ACCESSORS(normal_type_cache, Object)
// Add the code object to the cache.
- MUST_USE_RESULT MaybeObject* Update(String* name, Code* code);
+ MUST_USE_RESULT MaybeObject* Update(Name* name, Code* code);
// Lookup code object in the cache. Returns code object if found and undefined
// if not.
- Object* Lookup(String* name, Code::Flags flags);
+ Object* Lookup(Name* name, Code::Flags flags);
// Get the internal index of a code object in the cache. Returns -1 if the
// code object is not in that cache. This index can be used to later call
static const int kSize = kNormalTypeCacheOffset + kPointerSize;
private:
- MUST_USE_RESULT MaybeObject* UpdateDefaultCache(String* name, Code* code);
- MUST_USE_RESULT MaybeObject* UpdateNormalTypeCache(String* name, Code* code);
- Object* LookupDefaultCache(String* name, Code::Flags flags);
- Object* LookupNormalTypeCache(String* name, Code::Flags flags);
+ MUST_USE_RESULT MaybeObject* UpdateDefaultCache(Name* name, Code* code);
+ MUST_USE_RESULT MaybeObject* UpdateNormalTypeCache(Name* name, Code* code);
+ Object* LookupDefaultCache(Name* name, Code::Flags flags);
+ Object* LookupNormalTypeCache(Name* name, Code::Flags flags);
// Code cache layout of the default cache. Elements are alternating name and
// code objects for non normal load/store/call IC's.
class CodeCacheHashTable: public HashTable<CodeCacheHashTableShape,
HashTableKey*> {
public:
- Object* Lookup(String* name, Code::Flags flags);
- MUST_USE_RESULT MaybeObject* Put(String* name, Code* code);
+ Object* Lookup(Name* name, Code::Flags flags);
+ MUST_USE_RESULT MaybeObject* Put(Name* name, Code* code);
- int GetIndex(String* name, Code::Flags flags);
+ int GetIndex(Name* name, Code::Flags flags);
void RemoveByIndex(int index);
static inline CodeCacheHashTable* cast(Object* obj);
// Returns a hash value used for the property table
inline uint32_t Hash();
+ // Equality operations.
+ inline bool Equals(Name* other);
+
+ // Conversion.
+ inline bool AsArrayIndex(uint32_t* index);
+
// Casting.
static inline Name* cast(Object* obj);
+ DECLARE_PRINTER(Name)
+
// Layout description.
static const int kHashFieldOffset = HeapObject::kHeaderSize;
static const int kSize = kHashFieldOffset + kPointerSize;
// Casting.
static inline JSProxy* cast(Object* obj);
- bool HasPropertyWithHandler(String* name);
+ bool HasPropertyWithHandler(Name* name);
bool HasElementWithHandler(uint32_t index);
MUST_USE_RESULT MaybeObject* GetPropertyWithHandler(
Object* receiver,
- String* name);
+ Name* name);
MUST_USE_RESULT MaybeObject* GetElementWithHandler(
Object* receiver,
uint32_t index);
MUST_USE_RESULT MaybeObject* SetPropertyWithHandler(
JSReceiver* receiver,
- String* name,
+ Name* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode);
// otherwise set it to false.
MUST_USE_RESULT MaybeObject* SetPropertyViaPrototypesWithHandler(
JSReceiver* receiver,
- String* name,
+ Name* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool* done);
MUST_USE_RESULT MaybeObject* DeletePropertyWithHandler(
- String* name,
+ Name* name,
DeleteMode mode);
MUST_USE_RESULT MaybeObject* DeleteElementWithHandler(
uint32_t index,
MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler(
JSReceiver* receiver,
- String* name);
+ Name* name);
MUST_USE_RESULT PropertyAttributes GetElementAttributeWithHandler(
JSReceiver* receiver,
uint32_t index);
namespace v8 {
namespace internal {
-const char* StringsStorage::GetFunctionName(String* name) {
+const char* StringsStorage::GetFunctionName(Name* name) {
return GetFunctionName(GetName(name));
}
}
-const char* StringsStorage::GetName(String* name) {
+const char* StringsStorage::GetName(Name* name) {
if (name->IsString()) {
- int length = Min(kMaxNameSize, name->length());
+ String* str = String::cast(name);
+ int length = Min(kMaxNameSize, str->length());
SmartArrayPointer<char> data =
- name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL, 0, length);
+ str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL, 0, length);
uint32_t hash = StringHasher::HashSequentialString(
*data, length, name->GetHeap()->HashSeed());
return AddOrDisposeString(data.Detach(), hash);
+ } else if (name->IsSymbol()) {
+ return "<symbol>";
}
return "";
}
CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
- String* name,
+ Name* name,
String* resource_name,
int line_number) {
CodeEntry* entry = new CodeEntry(tag,
CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
const char* name_prefix,
- String* name) {
+ Name* name) {
CodeEntry* entry = new CodeEntry(tag,
name_prefix,
GetName(name),
const char* GetCopy(const char* src);
const char* GetFormatted(const char* format, ...);
const char* GetVFormatted(const char* format, va_list args);
- const char* GetName(String* name);
+ const char* GetName(Name* name);
const char* GetName(int index);
- inline const char* GetFunctionName(String* name);
+ inline const char* GetFunctionName(Name* name);
inline const char* GetFunctionName(const char* name);
size_t GetUsedMemorySize() const;
const char* title,
double actual_sampling_rate);
List<CpuProfile*>* Profiles(int security_token_id);
- const char* GetName(String* name) {
+ const char* GetName(Name* name) {
return function_and_resource_names_.GetName(name);
}
const char* GetName(int args_count) {
bool HasDetachedProfiles() { return detached_profiles_.length() > 0; }
CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
- String* name, String* resource_name, int line_number);
+ Name* name, String* resource_name, int line_number);
CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, const char* name);
CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
- const char* name_prefix, String* name);
+ const char* name_prefix, Name* name);
CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, int args_count);
CodeEntry* NewCodeEntry(int security_token_id);
static const int kMaxSimultaneousProfiles = 100;
private:
- const char* GetFunctionName(String* name) {
+ const char* GetFunctionName(Name* name) {
return function_and_resource_names_.GetFunctionName(name);
}
const char* GetFunctionName(const char* name) {
explicit ProfileGenerator(CpuProfilesCollection* profiles);
INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
- String* name,
+ Name* name,
String* resource_name,
int line_number)) {
return profiles_->NewCodeEntry(tag, name, resource_name, line_number);
INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
const char* name_prefix,
- String* name)) {
+ Name* name)) {
return profiles_->NewCodeEntry(tag, name_prefix, name);
}
return Smi::cast(value)->value();
}
- MUST_USE_RESULT MaybeObject* KeyToInternalizedString() {
- if (!StringShape(key_).IsInternalized()) {
- MaybeObject* maybe_result = HEAP->InternalizeString(key_);
+ MUST_USE_RESULT MaybeObject* KeyToUniqueName() {
+ if (!key_->IsUniqueName()) {
+ MaybeObject* maybe_result = HEAP->InternalizeString(String::cast(key_));
if (!maybe_result->To(&key_)) return maybe_result;
}
return key_;
}
- String* GetKey() { return key_; }
+ Name* GetKey() { return key_; }
Object* GetValue() { return value_; }
PropertyDetails GetDetails() { return details_; }
void SetSortedKeyIndex(int index) { details_ = details_.set_pointer(index); }
private:
- String* key_;
+ Name* key_;
Object* value_;
PropertyDetails details_;
protected:
Descriptor() : details_(Smi::FromInt(0)) {}
- void Init(String* key, Object* value, PropertyDetails details) {
+ void Init(Name* key, Object* value, PropertyDetails details) {
key_ = key;
value_ = value;
details_ = details;
}
- Descriptor(String* key, Object* value, PropertyDetails details)
+ Descriptor(Name* key, Object* value, PropertyDetails details)
: key_(key),
value_(value),
details_(details) { }
- Descriptor(String* key,
+ Descriptor(Name* key,
Object* value,
PropertyAttributes attributes,
PropertyType type,
class FieldDescriptor: public Descriptor {
public:
- FieldDescriptor(String* key,
+ FieldDescriptor(Name* key,
int field_index,
PropertyAttributes attributes,
int index = 0)
class ConstantFunctionDescriptor: public Descriptor {
public:
- ConstantFunctionDescriptor(String* key,
+ ConstantFunctionDescriptor(Name* key,
JSFunction* function,
PropertyAttributes attributes,
int index)
class CallbacksDescriptor: public Descriptor {
public:
- CallbacksDescriptor(String* key,
+ CallbacksDescriptor(Name* key,
Object* foreign,
PropertyAttributes attributes,
int index = 0)
if (IS_UNDEFINED(handler.enumerate)) {
return %Apply(DerivedEnumerateTrap, handler, [], 0, 0)
} else {
- return ToStringArray(handler.enumerate(), "enumerate")
+ return ToNameArray(handler.enumerate(), "enumerate")
}
}
static AccessCheckResult CheckPropertyAccess(
JSObject* obj,
- String* name,
+ Name* name,
v8::AccessType access_type) {
uint32_t index;
if (name->AsArrayIndex(&index)) {
static MaybeObject* GetOwnProperty(Isolate* isolate,
Handle<JSObject> obj,
- Handle<String> name) {
+ Handle<Name> name) {
Heap* heap = isolate->heap();
// Due to some WebKit tests, we want to make sure that we do not log
// more than one access failure here.
ASSERT(args.length() == 2);
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
- CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
return GetOwnProperty(isolate, obj, name);
}
} else { // Dictionary properties.
// Directly manipulate the property details.
int entry = function->property_dictionary()->FindEntry(name);
- ASSERT(entry != StringDictionary::kNotFound);
+ ASSERT(entry != NameDictionary::kNotFound);
PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
PropertyDetails new_details(
static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
return GetElementOrCharAt(isolate, object, index);
}
- // Convert the key to a string - possibly by calling back into JavaScript.
- Handle<String> name;
- if (key->IsString()) {
- name = Handle<String>::cast(key);
+ // Convert the key to a name - possibly by calling back into JavaScript.
+ Handle<Name> name;
+ if (key->IsName()) {
+ name = Handle<Name>::cast(key);
} else {
bool has_pending_exception = false;
Handle<Object> converted =
Execution::ToString(key, &has_pending_exception);
if (has_pending_exception) return Failure::Exception();
- name = Handle<String>::cast(converted);
+ name = Handle<Name>::cast(converted);
}
// Check if the name is trivially convertible to an index and get
}
-// KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
+// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
NoHandleAllocation ha(isolate);
ASSERT(args.length() == 2);
if (args[0]->IsJSObject()) {
if (!args[0]->IsJSGlobalProxy() &&
!args[0]->IsAccessCheckNeeded() &&
- args[1]->IsString()) {
+ args[1]->IsName()) {
JSObject* receiver = JSObject::cast(args[0]);
- String* key = String::cast(args[1]);
+ Name* key = Name::cast(args[1]);
if (receiver->HasFastProperties()) {
// Attempt to use lookup cache.
Map* receiver_map = receiver->map();
}
} else {
// Attempt dictionary lookup.
- StringDictionary* dictionary = receiver->property_dictionary();
+ NameDictionary* dictionary = receiver->property_dictionary();
int entry = dictionary->FindEntry(key);
- if ((entry != StringDictionary::kNotFound) &&
+ if ((entry != NameDictionary::kNotFound) &&
(dictionary->DetailsAt(entry).type() == NORMAL)) {
Object* value = dictionary->ValueAt(entry);
if (!receiver->IsGlobalObject()) return value;
}
}
} else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
- // JSObject without a string key. If the key is a Smi, check for a
+ // JSObject without a name key. If the key is a Smi, check for a
// definite out-of-bounds access to elements, which is a strong indicator
// that subsequent accesses will also call the runtime. Proactively
// transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
RUNTIME_ASSERT(!obj->IsNull());
- CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
RUNTIME_ASSERT(IsValidAccessor(getter));
CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
ASSERT(args.length() == 4);
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
- CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
CONVERT_SMI_ARG_CHECKED(unchecked, 3);
RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
- CONVERT_ARG_HANDLE_CHECKED(String, key, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
LookupResult lookup(isolate);
object->LookupRealNamedProperty(*key, &lookup);
if (!lookup.IsFound()) return isolate->heap()->undefined_value();
if (object->IsJSProxy()) {
bool has_pending_exception = false;
- Handle<Object> name = Execution::ToString(key, &has_pending_exception);
+ Handle<Object> name = key->IsSymbol()
+ ? key : Execution::ToString(key, &has_pending_exception);
if (has_pending_exception) return Failure::Exception();
return JSProxy::cast(*object)->SetProperty(
- String::cast(*name), *value, attr, strict_mode);
+ Name::cast(*name), *value, attr, strict_mode);
}
// If the object isn't a JavaScript object, we ignore the store.
return *value;
}
- if (key->IsString()) {
+ if (key->IsName()) {
Handle<Object> result;
- if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
+ Handle<Name> name = Handle<Name>::cast(key);
+ if (name->AsArrayIndex(&index)) {
result = JSObject::SetElement(
js_object, index, value, attr, strict_mode, set_mode);
} else {
- Handle<String> key_string = Handle<String>::cast(key);
- key_string->TryFlatten();
+ if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
result = JSReceiver::SetProperty(
- js_object, key_string, value, attr, strict_mode);
+ js_object, name, value, attr, strict_mode);
}
if (result.is_null()) return Failure::Exception();
return *value;
index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
}
- if (key->IsString()) {
- if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
+ if (key->IsName()) {
+ Handle<Name> name = Handle<Name>::cast(key);
+ if (name->AsArrayIndex(&index)) {
return js_object->SetElement(
index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
} else {
- Handle<String> key_string = Handle<String>::cast(key);
- key_string->TryFlatten();
- return js_object->SetLocalPropertyIgnoreAttributes(*key_string,
- *value,
- attr);
+ if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
+ return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
}
}
return receiver->DeleteElement(index, JSReceiver::FORCE_DELETION);
}
- Handle<String> key_string;
- if (key->IsString()) {
- key_string = Handle<String>::cast(key);
+ Handle<Name> name;
+ if (key->IsName()) {
+ name = Handle<Name>::cast(key);
} else {
// Call-back into JavaScript to convert the key to a string.
bool has_pending_exception = false;
Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
if (has_pending_exception) return Failure::Exception();
- key_string = Handle<String>::cast(converted);
+ name = Handle<String>::cast(converted);
}
- key_string->TryFlatten();
- return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION);
+ if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
+ return receiver->DeleteProperty(*name, JSReceiver::FORCE_DELETION);
}
NoHandleAllocation ha(isolate);
RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
CONVERT_ARG_CHECKED(JSObject, object, 0);
- CONVERT_ARG_CHECKED(String, name, 1);
+ CONVERT_ARG_CHECKED(Name, name, 1);
// Compute attributes.
PropertyAttributes attributes = NONE;
if (args.length() == 4) {
ASSERT(args.length() == 3);
CONVERT_ARG_CHECKED(JSReceiver, object, 0);
- CONVERT_ARG_CHECKED(String, key, 1);
+ CONVERT_ARG_CHECKED(Name, key, 1);
CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
return object->DeleteProperty(key, (strict_mode == kStrictMode)
? JSReceiver::STRICT_DELETION
static Object* HasLocalPropertyImplementation(Isolate* isolate,
Handle<JSObject> object,
- Handle<String> key) {
+ Handle<Name> key) {
if (object->HasLocalProperty(*key)) return isolate->heap()->true_value();
// Handle hidden prototypes. If there's a hidden prototype above this thing
// then we have to check it for properties, because they are supposed to
RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
NoHandleAllocation ha(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(String, key, 1);
+ CONVERT_ARG_CHECKED(Name, key, 1);
uint32_t index;
const bool key_is_array_index = key->AsArrayIndex(&index);
HandleScope scope(isolate);
return HasLocalPropertyImplementation(isolate,
Handle<JSObject>(object),
- Handle<String>(key));
+ Handle<Name>(key));
} else if (obj->IsString() && key_is_array_index) {
// Well, there is one exception: Handle [] on strings.
String* string = String::cast(obj);
NoHandleAllocation na(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
- CONVERT_ARG_CHECKED(String, key, 1);
+ CONVERT_ARG_CHECKED(Name, key, 1);
bool result = receiver->HasProperty(key);
if (isolate->has_pending_exception()) return Failure::Exception();
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(JSObject, object, 0);
- CONVERT_ARG_CHECKED(String, key, 1);
+ CONVERT_ARG_CHECKED(Name, key, 1);
PropertyAttributes att = object->GetLocalPropertyAttribute(key);
return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
for (int i = 0; i < length; i++) {
Object* entry = contents->get(i);
- if (entry->IsString()) {
+ if (entry->IsName()) {
copy->set(i, entry);
} else {
ASSERT(entry->IsNumber());
return frame->GetParameter(index);
}
+ if (args[0]->IsSymbol()) {
+ // Lookup in the initial Object.prototype object.
+ return isolate->initial_object_prototype()->GetProperty(
+ Symbol::cast(args[0]));
+ }
+
// Convert the key to a string.
HandleScope scope(isolate);
bool exception = false;
RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
ASSERT(args.length() == 3);
CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
- CONVERT_ARG_CHECKED(String, name, 1);
+ CONVERT_ARG_CHECKED(Name, name, 1);
CONVERT_SMI_ARG_CHECKED(flag, 2);
AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
static MaybeObject* DebugLookupResultValue(Heap* heap,
Object* receiver,
- String* name,
+ Name* name,
LookupResult* result,
bool* caught_exception) {
Object* value;
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
- CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
// Make sure to set the current context to the context before the debugger was
// entered (if the debugger is entered). The reason for switching context here
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
- CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
LookupResult result(isolate);
obj->Lookup(*name, &result);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
RUNTIME_ASSERT(obj->HasNamedInterceptor());
- CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
PropertyAttributes attributes;
return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
Object* dictionary) {
ASSERT(Isolate::Current()->heap() == heap);
ASSERT(dictionary != NULL);
- ASSERT(StringDictionary::cast(dictionary)->NumberOfElements() == 0);
+ ASSERT(NameDictionary::cast(dictionary)->NumberOfElements() == 0);
for (int i = 0; i < kNumFunctions; ++i) {
Object* name_string;
{ MaybeObject* maybe_name_string =
heap->InternalizeUtf8String(kIntrinsicFunctions[i].name);
if (!maybe_name_string->ToObject(&name_string)) return maybe_name_string;
}
- StringDictionary* string_dictionary = StringDictionary::cast(dictionary);
- { MaybeObject* maybe_dictionary = string_dictionary->Add(
+ NameDictionary* name_dictionary = NameDictionary::cast(dictionary);
+ { MaybeObject* maybe_dictionary = name_dictionary->Add(
String::cast(name_string),
Smi::FromInt(i),
PropertyDetails(NONE, NORMAL));
// ECMA-262, section 11.4.1, page 46.
function DELETE(key, strict) {
- return %DeleteProperty(%ToObject(this), %ToString(key), strict);
+ return %DeleteProperty(%ToObject(this), %ToName(key), strict);
}
throw %MakeTypeError('invalid_in_operator_use', [this, x]);
}
return %_IsNonNegativeSmi(this) ?
- %HasElement(x, this) : %HasProperty(x, %ToString(this));
+ %HasElement(x, this) : %HasProperty(x, %ToName(this));
}
// has a property with the given key; return the key as a string if
// it has. Otherwise returns 0 (smi). Used in for-in statements.
function FILTER_KEY(key) {
- var string = %ToString(key);
+ var string = %ToName(key);
if (%HasProperty(this, string)) return string;
return 0;
}
}
+// ES6 symbols
+function ToName(x) {
+ return IS_SYMBOL(x) ? x : %ToString(x);
+}
+
+
// ECMA-262, section 9.9, page 36.
function ToObject(x) {
if (IS_STRING(x)) return new $String(x);
}
-Code* StubCache::Set(String* name, Map* map, Code* code) {
+Code* StubCache::Set(Name* name, Map* map, Code* code) {
// Get the flags from the code.
Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
// Validate that the name does not move on scavenge, and that we
- // can use identity checks instead of string equality checks.
+ // can use identity checks instead of structural equality checks.
ASSERT(!heap()->InNewSpace(name));
- ASSERT(name->IsInternalizedString());
+ ASSERT(name->IsUniqueName());
// The state bits are not important to the hash function because
// the stub cache only contains monomorphic stubs. Make sure that
}
-Handle<Code> StubCache::FindStub(Handle<String> name,
+Handle<Code> StubCache::FindStub(Handle<Name> name,
Handle<JSObject> stub_holder,
Code::Kind kind,
Code::StubType type,
}
-Handle<Code> StubCache::FindHandler(Handle<String> name,
+Handle<Code> StubCache::FindHandler(Handle<Name> name,
Handle<JSObject> handler_holder,
Code::Kind kind,
Code::StubType type) {
Handle<Code> StubCache::ComputeMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
- Handle<String> name) {
+ Handle<Name> name) {
Handle<Code> ic = FindStub(name, receiver, Code::LOAD_IC,
handler->type(), Code::IC_FRAGMENT);
if (!ic.is_null()) return ic;
Handle<Code> StubCache::ComputeKeyedMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
- Handle<String> name) {
+ Handle<Name> name) {
Handle<Code> ic = FindStub(name, receiver, Code::KEYED_LOAD_IC,
handler->type(), Code::IC_FRAGMENT);
if (!ic.is_null()) return ic;
}
-Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
Handle<JSObject> receiver) {
// If no global objects are present in the prototype chain, the load
// nonexistent IC stub can be shared for all names for a given map
// there are global objects involved, we need to check global
// property cells in the stub and therefore the stub will be
// specific to the name.
- Handle<String> cache_name = factory()->empty_string();
+ Handle<Name> cache_name = factory()->empty_string();
Handle<JSObject> current;
Handle<Object> next = receiver;
Handle<GlobalObject> global;
}
-Handle<Code> StubCache::ComputeLoadField(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadField(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
PropertyIndex field) {
Handle<Code> StubCache::ComputeLoadCallback(
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
}
-Handle<Code> StubCache::ComputeLoadViaGetter(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadViaGetter(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<JSFunction> getter) {
}
-Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadConstant(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<JSFunction> value) {
}
-Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadInterceptor(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
}
-Handle<Code> StubCache::ComputeLoadNormal(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadNormal(Handle<Name> name,
Handle<JSObject> receiver) {
return isolate_->builtins()->LoadIC_Normal();
}
-Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadGlobal(Handle<Name> name,
Handle<JSObject> receiver,
Handle<GlobalObject> holder,
Handle<JSGlobalPropertyCell> cell,
}
-Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name,
+Handle<Code> StubCache::ComputeKeyedLoadField(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
PropertyIndex field) {
}
-Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name,
+Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<JSFunction> value) {
}
-Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name,
+Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> StubCache::ComputeKeyedLoadCallback(
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
}
-Handle<Code> StubCache::ComputeStoreField(Handle<String> name,
+Handle<Code> StubCache::ComputeStoreField(Handle<Name> name,
Handle<JSObject> receiver,
int field_index,
Handle<Map> transition,
Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) {
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC);
- Handle<String> name =
+ Handle<Name> name =
isolate()->factory()->KeyedLoadElementMonomorphic_string();
Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_);
ASSERT(stub_kind == KeyedStoreIC::STORE_NO_TRANSITION ||
stub_kind == KeyedStoreIC::STORE_AND_GROW_NO_TRANSITION);
- Handle<String> name = stub_kind == KeyedStoreIC::STORE_NO_TRANSITION
+ Handle<Name> name = stub_kind == KeyedStoreIC::STORE_NO_TRANSITION
? isolate()->factory()->KeyedStoreElementMonomorphic_string()
: isolate()->factory()->KeyedStoreAndGrowElementMonomorphic_string();
}
-Handle<Code> StubCache::ComputeStoreGlobal(Handle<String> name,
+Handle<Code> StubCache::ComputeStoreGlobal(Handle<Name> name,
Handle<GlobalObject> receiver,
Handle<JSGlobalPropertyCell> cell,
StrictModeFlag strict_mode) {
Handle<Code> StubCache::ComputeStoreCallback(
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback,
}
-Handle<Code> StubCache::ComputeStoreViaSetter(Handle<String> name,
+Handle<Code> StubCache::ComputeStoreViaSetter(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<JSFunction> setter,
}
-Handle<Code> StubCache::ComputeStoreInterceptor(Handle<String> name,
+Handle<Code> StubCache::ComputeStoreInterceptor(Handle<Name> name,
Handle<JSObject> receiver,
StrictModeFlag strict_mode) {
Code::Flags flags = Code::ComputeMonomorphicFlags(
return code;
}
-Handle<Code> StubCache::ComputeKeyedStoreField(Handle<String> name,
+Handle<Code> StubCache::ComputeKeyedStoreField(Handle<Name> name,
Handle<JSObject> receiver,
int field_index,
Handle<Map> transition,
Handle<Code> StubCache::ComputeCallConstant(int argc,
Code::Kind kind,
Code::ExtraICState extra_state,
- Handle<String> name,
+ Handle<Name> name,
Handle<Object> object,
Handle<JSObject> holder,
Handle<JSFunction> function) {
Handle<Code> StubCache::ComputeCallField(int argc,
Code::Kind kind,
Code::ExtraICState extra_state,
- Handle<String> name,
+ Handle<Name> name,
Handle<Object> object,
Handle<JSObject> holder,
PropertyIndex index) {
Handle<Code> StubCache::ComputeCallInterceptor(int argc,
Code::Kind kind,
Code::ExtraICState extra_state,
- Handle<String> name,
+ Handle<Name> name,
Handle<Object> object,
Handle<JSObject> holder) {
// Compute the check type and the map.
Handle<Code> StubCache::ComputeCallGlobal(int argc,
Code::Kind kind,
Code::ExtraICState extra_state,
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> receiver,
Handle<GlobalObject> holder,
Handle<JSGlobalPropertyCell> cell,
Handle<Code> StubCache::ComputePolymorphicIC(MapHandleList* receiver_maps,
CodeHandleList* handlers,
- Handle<String> name) {
+ Handle<Name> name) {
LoadStubCompiler ic_compiler(isolate_);
Handle<Code> ic = ic_compiler.CompilePolymorphicIC(
receiver_maps, handlers, name, Code::NORMAL, PROPERTY);
void StubCache::CollectMatchingMaps(SmallMapList* types,
- String* name,
+ Name* name,
Code::Flags flags,
Handle<Context> native_context,
Zone* zone) {
v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
ASSERT(fun != NULL);
ASSERT(callback->IsCompatibleReceiver(recv));
- Handle<String> name = args.at<String>(2);
+ Handle<Name> name = args.at<Name>(2);
Handle<Object> value = args.at<Object>(3);
HandleScope scope(isolate);
+
+ // TODO(rossberg): Support symbols in the API.
+ if (name->IsSymbol()) return *value;
+ Handle<String> str = Handle<String>::cast(name);
+
LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
CustomArguments custom_args(isolate, callback->data(), recv, recv);
v8::AccessorInfo info(custom_args.end());
// Leaving JavaScript.
VMState state(isolate, EXTERNAL);
ExternalCallbackScope call_scope(isolate, setter_address);
- fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
+ fun(v8::Utils::ToLocal(str), v8::Utils::ToLocal(value), info);
}
RETURN_IF_SCHEDULED_EXCEPTION(isolate);
return *value;
* provide any value for the given name.
*/
RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
- Handle<String> name_handle = args.at<String>(0);
+ Handle<Name> name_handle = args.at<Name>(0);
Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
ASSERT(args[2]->IsJSObject()); // Receiver.
ASSERT(args[5]->IsSmi()); // Isolate.
ASSERT(args.length() == 6);
+ // TODO(rossberg): Support symbols in the API.
+ if (name_handle->IsSymbol())
+ return isolate->heap()->no_interceptor_result_sentinel();
+ Handle<String> name = Handle<String>::cast(name_handle);
+
Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
v8::NamedPropertyGetter getter =
FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
{
// Leaving JavaScript.
VMState state(isolate, EXTERNAL);
- r = getter(v8::Utils::ToLocal(name_handle), info);
+ r = getter(v8::Utils::ToLocal(name), info);
}
RETURN_IF_SCHEDULED_EXCEPTION(isolate);
if (!r.IsEmpty()) {
}
-static MaybeObject* ThrowReferenceError(Isolate* isolate, String* name) {
+static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) {
// If the load is non-contextual, just return the undefined result.
// Note that both keyed and non-keyed loads may end up here, so we
// can't use either LoadIC or KeyedLoadIC constructors.
// Throw a reference error.
HandleScope scope(isolate);
- Handle<String> name_handle(name);
+ Handle<Name> name_handle(name);
Handle<Object> error =
FACTORY->NewReferenceError("not_defined",
HandleVector(&name_handle, 1));
static MaybeObject* LoadWithInterceptor(Arguments* args,
PropertyAttributes* attrs) {
- Handle<String> name_handle = args->at<String>(0);
+ Handle<Name> name_handle = args->at<Name>(0);
Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
Handle<JSObject> receiver_handle = args->at<JSObject>(2);
Isolate* isolate = receiver_handle->GetIsolate();
+ // TODO(rossberg): Support symbols in the API.
+ if (name_handle->IsSymbol())
+ return holder_handle->GetPropertyPostInterceptor(
+ *receiver_handle, *name_handle, attrs);
+ Handle<String> name = Handle<String>::cast(name_handle);
+
Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
v8::NamedPropertyGetter getter =
FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
{
// Leaving JavaScript.
VMState state(isolate, EXTERNAL);
- r = getter(v8::Utils::ToLocal(name_handle), info);
+ r = getter(v8::Utils::ToLocal(name), info);
}
RETURN_IF_SCHEDULED_EXCEPTION(isolate);
if (!r.IsEmpty()) {
// If the property is present, return it.
if (attr != ABSENT) return result;
- return ThrowReferenceError(isolate, String::cast(args[0]));
+ return ThrowReferenceError(isolate, Name::cast(args[0]));
}
RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
ASSERT(args.length() == 4);
JSObject* recv = JSObject::cast(args[0]);
- String* name = String::cast(args[1]);
+ Name* name = Name::cast(args[1]);
Object* value = args[2];
ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode);
StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
- Handle<String> name) {
- return (FLAG_print_code_stubs && !name.is_null())
- ? GetCodeWithFlags(flags, *name->ToCString())
+ Handle<Name> name) {
+ return (FLAG_print_code_stubs && !name.is_null() && name->IsString())
+ ? GetCodeWithFlags(flags, *Handle<String>::cast(name)->ToCString())
: GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
}
void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
LookupResult* lookup) {
holder->LocalLookupRealNamedProperty(*name, lookup);
if (lookup->IsFound()) return;
Register BaseLoadStubCompiler::HandlerFrontendHeader(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Label* miss) {
// Check the prototype chain.
return CheckPrototypes(object, object_reg, holder,
Register BaseLoadStubCompiler::HandlerFrontend(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Label* success) {
Label miss;
Handle<Code> BaseLoadStubCompiler::CompileLoadField(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
PropertyIndex field) {
Label miss;
Handle<Code> BaseLoadStubCompiler::CompileLoadConstant(
Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Handle<JSFunction> value) {
Label success;
HandlerFrontend(object, receiver(), holder, name, &success);
Handle<Code> BaseLoadStubCompiler::CompileLoadCallback(
Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
Label success;
Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor(
Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name) {
+ Handle<Name> name) {
Label success;
LookupResult lookup(isolate());
void BaseLoadStubCompiler::GenerateLoadPostInterceptor(
Register interceptor_reg,
Handle<JSObject> interceptor_holder,
- Handle<String> name,
+ Handle<Name> name,
LookupResult* lookup) {
Label success;
Handle<JSObject> holder(lookup->holder());
Handle<Code> BaseLoadStubCompiler::CompileMonomorphicIC(
Handle<Map> receiver_map,
Handle<Code> handler,
- Handle<String> name) {
+ Handle<Name> name) {
MapHandleList receiver_maps(1);
receiver_maps.Add(receiver_map);
CodeHandleList handlers(1);
Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Handle<JSFunction> getter) {
Label success;
HandlerFrontend(object, receiver(), holder, name, &success);
#undef __
-void LoadStubCompiler::JitEvent(Handle<String> name, Handle<Code> code) {
+void LoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
}
-void KeyedLoadStubCompiler::JitEvent(Handle<String> name, Handle<Code> code) {
+void KeyedLoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
}
Handle<Code> BaseLoadStubCompiler::GetCode(Code::IcFragment fragment,
Code::StubType type,
- Handle<String> name,
+ Handle<Name> name,
InlineCacheState state) {
Code::Flags flags = Code::ComputeFlags(kind(), state, fragment, type);
Handle<Code> code = GetCodeWithFlags(flags, name);
Handle<Code> StoreStubCompiler::GetCode(Code::StubType type,
- Handle<String> name) {
+ Handle<Name> name) {
Code::Flags flags = Code::ComputeMonomorphicFlags(
Code::STORE_IC, strict_mode_, type);
Handle<Code> code = GetCodeWithFlags(flags, name);
Handle<Code> KeyedStoreStubCompiler::GetCode(Code::StubType type,
- Handle<String> name,
+ Handle<Name> name,
InlineCacheState state) {
Code::ExtraICState extra_state =
Code::ComputeExtraICState(grow_mode_, strict_mode_);
Handle<Code> CallStubCompiler::GetCode(Code::StubType type,
- Handle<String> name) {
+ Handle<Name> name) {
int argc = arguments_.immediate();
Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
extra_state_,
class StubCache {
public:
struct Entry {
- String* key;
+ Name* key;
Code* value;
Map* map;
};
Handle<JSObject> StubHolder(Handle<JSObject> receiver,
Handle<JSObject> holder);
- Handle<Code> FindStub(Handle<String> name,
+ Handle<Code> FindStub(Handle<Name> name,
Handle<JSObject> stub_holder,
Code::Kind kind,
Code::StubType type,
Code::IcFragment fragment);
- Handle<Code> FindHandler(Handle<String> name,
+ Handle<Code> FindHandler(Handle<Name> name,
Handle<JSObject> stub_holder,
Code::Kind kind,
Code::StubType type);
Handle<Code> ComputeMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
- Handle<String> name);
+ Handle<Name> name);
Handle<Code> ComputeKeyedMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
- Handle<String> name);
+ Handle<Name> name);
// Computes the right stub matching. Inserts the result in the
// cache before returning. This might compile a stub if needed.
- Handle<Code> ComputeLoadNonexistent(Handle<String> name,
+ Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
Handle<JSObject> object);
- Handle<Code> ComputeLoadField(Handle<String> name,
+ Handle<Code> ComputeLoadField(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
PropertyIndex field_index);
- Handle<Code> ComputeLoadCallback(Handle<String> name,
+ Handle<Code> ComputeLoadCallback(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback);
- Handle<Code> ComputeLoadViaGetter(Handle<String> name,
+ Handle<Code> ComputeLoadViaGetter(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<JSFunction> getter);
- Handle<Code> ComputeLoadConstant(Handle<String> name,
+ Handle<Code> ComputeLoadConstant(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<JSFunction> value);
- Handle<Code> ComputeLoadInterceptor(Handle<String> name,
+ Handle<Code> ComputeLoadInterceptor(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder);
- Handle<Code> ComputeLoadNormal(Handle<String> name,
+ Handle<Code> ComputeLoadNormal(Handle<Name> name,
Handle<JSObject> object);
- Handle<Code> ComputeLoadGlobal(Handle<String> name,
+ Handle<Code> ComputeLoadGlobal(Handle<Name> name,
Handle<JSObject> object,
Handle<GlobalObject> holder,
Handle<JSGlobalPropertyCell> cell,
// ---
- Handle<Code> ComputeKeyedLoadField(Handle<String> name,
+ Handle<Code> ComputeKeyedLoadField(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
PropertyIndex field_index);
Handle<Code> ComputeKeyedLoadCallback(
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback);
- Handle<Code> ComputeKeyedLoadConstant(Handle<String> name,
+ Handle<Code> ComputeKeyedLoadConstant(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<JSFunction> value);
- Handle<Code> ComputeKeyedLoadInterceptor(Handle<String> name,
+ Handle<Code> ComputeKeyedLoadInterceptor(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder);
// ---
- Handle<Code> ComputeStoreField(Handle<String> name,
+ Handle<Code> ComputeStoreField(Handle<Name> name,
Handle<JSObject> object,
int field_index,
Handle<Map> transition,
Handle<Code> ComputeStoreNormal(StrictModeFlag strict_mode);
- Handle<Code> ComputeStoreGlobal(Handle<String> name,
+ Handle<Code> ComputeStoreGlobal(Handle<Name> name,
Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell,
StrictModeFlag strict_mode);
- Handle<Code> ComputeStoreCallback(Handle<String> name,
+ Handle<Code> ComputeStoreCallback(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback,
StrictModeFlag strict_mode);
- Handle<Code> ComputeStoreViaSetter(Handle<String> name,
+ Handle<Code> ComputeStoreViaSetter(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<JSFunction> setter,
StrictModeFlag strict_mode);
- Handle<Code> ComputeStoreInterceptor(Handle<String> name,
+ Handle<Code> ComputeStoreInterceptor(Handle<Name> name,
Handle<JSObject> object,
StrictModeFlag strict_mode);
// ---
- Handle<Code> ComputeKeyedStoreField(Handle<String> name,
+ Handle<Code> ComputeKeyedStoreField(Handle<Name> name,
Handle<JSObject> object,
int field_index,
Handle<Map> transition,
Handle<Code> ComputeCallField(int argc,
Code::Kind,
Code::ExtraICState extra_state,
- Handle<String> name,
+ Handle<Name> name,
Handle<Object> object,
Handle<JSObject> holder,
PropertyIndex index);
Handle<Code> ComputeCallConstant(int argc,
Code::Kind,
Code::ExtraICState extra_state,
- Handle<String> name,
+ Handle<Name> name,
Handle<Object> object,
Handle<JSObject> holder,
Handle<JSFunction> function);
Handle<Code> ComputeCallInterceptor(int argc,
Code::Kind,
Code::ExtraICState extra_state,
- Handle<String> name,
+ Handle<Name> name,
Handle<Object> object,
Handle<JSObject> holder);
Handle<Code> ComputeCallGlobal(int argc,
Code::Kind,
Code::ExtraICState extra_state,
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> object,
Handle<GlobalObject> holder,
Handle<JSGlobalPropertyCell> cell,
Handle<Code> ComputePolymorphicIC(MapHandleList* receiver_maps,
CodeHandleList* handlers,
- Handle<String> name);
+ Handle<Name> name);
// Finds the Code object stored in the Heap::non_monomorphic_cache().
Code* FindCallInitialize(int argc, RelocInfo::Mode mode, Code::Kind kind);
#endif
// Update cache for entry hash(name, map).
- Code* Set(String* name, Map* map, Code* code);
+ Code* Set(Name* name, Map* map, Code* code);
// Clear the lookup table (@ mark compact collection).
void Clear();
// Collect all maps that match the name and flags.
void CollectMatchingMaps(SmallMapList* types,
- String* name,
+ Name* name,
Code::Flags flags,
Handle<Context> native_context,
Zone* zone);
// Hash algorithm for the primary table. This algorithm is replicated in
// assembler for every architecture. Returns an index into the table that
// is scaled by 1 << kHeapObjectTagSize.
- static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
+ static int PrimaryOffset(Name* name, Code::Flags flags, Map* map) {
// This works well because the heap object tag size and the hash
// shift are equal. Shifting down the length field to get the
// hash code would effectively throw away two bits of the hash
// code.
- STATIC_ASSERT(kHeapObjectTagSize == String::kHashShift);
+ STATIC_ASSERT(kHeapObjectTagSize == Name::kHashShift);
// Compute the hash of the name (use entire hash field).
ASSERT(name->HasHashCode());
uint32_t field = name->hash_field();
// Hash algorithm for the secondary table. This algorithm is replicated in
// assembler for every architecture. Returns an index into the table that
// is scaled by 1 << kHeapObjectTagSize.
- static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
+ static int SecondaryOffset(Name* name, Code::Flags flags, int seed) {
// Use the seed from the primary cache in the secondary cache.
- uint32_t string_low32bits =
+ uint32_t name_low32bits =
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
// We always set the in_loop bit to zero when generating the lookup code
// so do it here too so the hash codes match.
uint32_t iflags =
(static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
- uint32_t key = (seed - string_low32bits) + iflags;
+ uint32_t key = (seed - name_low32bits) + iflags;
return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
}
// Compute the entry for a given offset in exactly the same way as
// we do in generated code. We generate an hash code that already
- // ends in String::kHashShift 0s. Then we multiply it so it is a multiple
+ // ends in Name::kHashShift 0s. Then we multiply it so it is a multiple
// of sizeof(Entry). This makes it easier to avoid making mistakes
// in the hashed offset computations.
static Entry* entry(Entry* table, int offset) {
- const int multiplier = sizeof(*table) >> String::kHashShift;
+ const int multiplier = sizeof(*table) >> Name::kHashShift;
return reinterpret_cast<Entry*>(
reinterpret_cast<Address>(table) + offset * multiplier);
}
Handle<JSObject> object,
int index,
Handle<Map> transition,
- Handle<String> name,
+ Handle<Name> name,
Register receiver_reg,
Register name_reg,
Register scratch1,
Register holder_reg,
Register scratch1,
Register scratch2,
- Handle<String> name,
+ Handle<Name> name,
Label* miss,
PrototypeCheckType check = CHECK_ALL_MAPS) {
return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
Register holder_reg,
Register scratch1,
Register scratch2,
- Handle<String> name,
+ Handle<Name> name,
int save_at_depth,
Label* miss,
PrototypeCheckType check = CHECK_ALL_MAPS);
protected:
Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
- Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<String> name);
+ Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<Name> name);
MacroAssembler* masm() { return &masm_; }
void set_failure(Failure* failure) { failure_ = failure; }
static void LookupPostInterceptor(Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
LookupResult* lookup);
Isolate* isolate() { return isolate_; }
Handle<Code> CompileLoadField(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
PropertyIndex index);
Handle<Code> CompileLoadCallback(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Handle<ExecutableAccessorInfo> callback);
Handle<Code> CompileLoadConstant(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Handle<JSFunction> value);
Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name);
+ Handle<Name> name);
Handle<Code> CompileMonomorphicIC(Handle<Map> receiver_map,
Handle<Code> handler,
- Handle<String> name);
+ Handle<Name> name);
Handle<Code> CompilePolymorphicIC(MapHandleList* receiver_maps,
CodeHandleList* handlers,
- Handle<String> name,
+ Handle<Name> name,
Code::StubType type,
IcCheckType check);
Register HandlerFrontendHeader(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Label* success);
void HandlerFrontendFooter(Label* success, Label* miss);
Register HandlerFrontend(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Label* success);
Register CallbackHandlerFrontend(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Label* success,
Handle<ExecutableAccessorInfo> callback);
void NonexistentHandlerFrontend(Handle<JSObject> object,
Handle<JSObject> last,
- Handle<String> name,
+ Handle<Name> name,
Label* success,
Handle<GlobalObject> global);
Handle<JSObject> object,
Handle<JSObject> holder,
LookupResult* lookup,
- Handle<String> name);
+ Handle<Name> name);
void GenerateLoadPostInterceptor(Register reg,
Handle<JSObject> interceptor_holder,
- Handle<String> name,
+ Handle<Name> name,
LookupResult* lookup);
Handle<Code> GetCode(Code::IcFragment fragment,
Code::StubType type,
- Handle<String> name,
+ Handle<Name> name,
InlineCacheState state = MONOMORPHIC);
Register receiver() { return registers_[0]; }
private:
virtual Code::Kind kind() = 0;
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) = 0;
- virtual void JitEvent(Handle<String> name, Handle<Code> code) = 0;
- virtual void GenerateNameCheck(Handle<String> name,
+ virtual void JitEvent(Handle<Name> name, Handle<Code> code) = 0;
+ virtual void GenerateNameCheck(Handle<Name> name,
Register name_reg,
Label* miss) { }
Register* registers_;
Handle<Code> CompileLoadNonexistent(Handle<JSObject> object,
Handle<JSObject> last,
- Handle<String> name,
+ Handle<Name> name,
Handle<GlobalObject> global);
static void GenerateLoadViaGetter(MacroAssembler* masm,
Handle<Code> CompileLoadViaGetter(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Handle<JSFunction> getter);
Handle<Code> CompileLoadGlobal(Handle<JSObject> object,
Handle<GlobalObject> holder,
Handle<JSGlobalPropertyCell> cell,
- Handle<String> name,
+ Handle<Name> name,
bool is_dont_delete);
static Register receiver() { return registers()[0]; }
return code->ic_state() == MONOMORPHIC
? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG;
}
- virtual void JitEvent(Handle<String> name, Handle<Code> code);
+ virtual void JitEvent(Handle<Name> name, Handle<Code> code);
};
return code->ic_state() == MONOMORPHIC
? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG;
}
- virtual void JitEvent(Handle<String> name, Handle<Code> code);
- virtual void GenerateNameCheck(Handle<String> name,
+ virtual void JitEvent(Handle<Name> name, Handle<Code> code);
+ virtual void GenerateNameCheck(Handle<Name> name,
Register name_reg,
Label* miss);
};
Handle<Code> CompileStoreField(Handle<JSObject> object,
int index,
Handle<Map> transition,
- Handle<String> name);
+ Handle<Name> name);
- Handle<Code> CompileStoreCallback(Handle<String> name,
+ Handle<Code> CompileStoreCallback(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback);
static void GenerateStoreViaSetter(MacroAssembler* masm,
Handle<JSFunction> setter);
- Handle<Code> CompileStoreViaSetter(Handle<String> name,
+ Handle<Code> CompileStoreViaSetter(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<JSFunction> setter);
Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
- Handle<String> name);
+ Handle<Name> name);
Handle<Code> CompileStoreGlobal(Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> holder,
- Handle<String> name);
+ Handle<Name> name);
private:
- Handle<Code> GetCode(Code::StubType type, Handle<String> name);
+ Handle<Code> GetCode(Code::StubType type, Handle<Name> name);
StrictModeFlag strict_mode_;
};
Handle<Code> CompileStoreField(Handle<JSObject> object,
int index,
Handle<Map> transition,
- Handle<String> name);
+ Handle<Name> name);
Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
private:
Handle<Code> GetCode(Code::StubType type,
- Handle<String> name,
+ Handle<Name> name,
InlineCacheState state = MONOMORPHIC);
StrictModeFlag strict_mode_;
Handle<Code> CompileCallField(Handle<JSObject> object,
Handle<JSObject> holder,
PropertyIndex index,
- Handle<String> name);
+ Handle<Name> name);
void CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
CheckType check,
Label* success);
Handle<Code> CompileCallConstant(Handle<Object> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
CheckType check,
Handle<JSFunction> function);
Handle<Code> CompileCallInterceptor(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name);
+ Handle<Name> name);
Handle<Code> CompileCallGlobal(Handle<JSObject> object,
Handle<GlobalObject> holder,
Handle<JSGlobalPropertyCell> cell,
Handle<JSFunction> function,
- Handle<String> name);
+ Handle<Name> name);
static bool HasCustomCallGenerator(Handle<JSFunction> function);
Handle<JSFunction> function,
Handle<String> name);
- Handle<Code> GetCode(Code::StubType type, Handle<String> name);
+ Handle<Code> GetCode(Code::StubType type, Handle<Name> name);
Handle<Code> GetCode(Handle<JSFunction> function);
const ParameterCount& arguments() { return arguments_; }
- void GenerateNameCheck(Handle<String> name, Label* miss);
+ void GenerateNameCheck(Handle<Name> name, Label* miss);
void GenerateGlobalReceiverCheck(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Label* miss);
// Generates code to load the function from the cell checking that
}
-String* TransitionArray::GetKey(int transition_number) {
+Name* TransitionArray::GetKey(int transition_number) {
if (IsSimpleTransition()) {
Map* target = GetTarget(kSimpleTransitionIndex);
int descriptor = target->LastAdded();
- String* key = target->instance_descriptors()->GetKey(descriptor);
+ Name* key = target->instance_descriptors()->GetKey(descriptor);
return key;
}
ASSERT(transition_number < number_of_transitions());
- return String::cast(get(ToKeyIndex(transition_number)));
+ return Name::cast(get(ToKeyIndex(transition_number)));
}
-void TransitionArray::SetKey(int transition_number, String* key) {
+void TransitionArray::SetKey(int transition_number, Name* key) {
ASSERT(!IsSimpleTransition());
ASSERT(transition_number < number_of_transitions());
set(ToKeyIndex(transition_number), key);
}
-int TransitionArray::Search(String* name) {
+int TransitionArray::Search(Name* name) {
if (IsSimpleTransition()) {
- String* key = GetKey(kSimpleTransitionIndex);
+ Name* key = GetKey(kSimpleTransitionIndex);
if (key->Equals(name)) return kSimpleTransitionIndex;
return kNotFound;
}
void TransitionArray::NoIncrementalWriteBarrierSet(int transition_number,
- String* key,
+ Name* key,
Map* target) {
FixedArray::NoIncrementalWriteBarrierSet(
this, ToKeyIndex(transition_number), key);
}
-static bool InsertionPointFound(String* key1, String* key2) {
+static bool InsertionPointFound(Name* key1, Name* key2) {
return key1->Hash() > key2->Hash();
}
MaybeObject* TransitionArray::NewWith(SimpleTransitionFlag flag,
- String* key,
+ Name* key,
Map* target,
Object* back_pointer) {
TransitionArray* result;
}
-MaybeObject* TransitionArray::CopyInsert(String* name, Map* target) {
+MaybeObject* TransitionArray::CopyInsert(Name* name, Map* target) {
TransitionArray* result;
int number_of_transitions = this->number_of_transitions();
class TransitionArray: public FixedArray {
public:
// Accessors for fetching instance transition at transition number.
- inline String* GetKey(int transition_number);
- inline void SetKey(int transition_number, String* value);
+ inline Name* GetKey(int transition_number);
+ inline void SetKey(int transition_number, Name* value);
inline Object** GetKeySlot(int transition_number);
int GetSortedKeyIndex(int transition_number) { return transition_number; }
- String* GetSortedKey(int transition_number) {
+ Name* GetSortedKey(int transition_number) {
return GetKey(transition_number);
}
// Allocate a new transition array with a single entry.
static MUST_USE_RESULT MaybeObject* NewWith(
SimpleTransitionFlag flag,
- String* key,
+ Name* key,
Map* target,
Object* back_pointer);
// Copy the transition array, inserting a new transition.
// TODO(verwaest): This should not cause an existing transition to be
// overwritten.
- MUST_USE_RESULT MaybeObject* CopyInsert(String* name, Map* target);
+ MUST_USE_RESULT MaybeObject* CopyInsert(Name* name, Map* target);
// Copy a single transition from the origin array.
inline void NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
int target_transition);
// Search a transition for a given property name.
- inline int Search(String* name);
+ inline int Search(Name* name);
// Allocates a TransitionArray.
MUST_USE_RESULT static MaybeObject* Allocate(int number_of_transitions);
}
inline void NoIncrementalWriteBarrierSet(int transition_number,
- String* key,
+ Name* key,
Map* target);
DISALLOW_IMPLICIT_CONSTRUCTORS(TransitionArray);
class MemoryChunk;
class SeededNumberDictionary;
class UnseededNumberDictionary;
-class StringDictionary;
+class NameDictionary;
template <typename T> class Handle;
class Heap;
class HeapObject;
class IC;
class InterceptorInfo;
+class JSReceiver;
class JSArray;
class JSFunction;
class JSObject;
template <typename Config, class Allocator = FreeStoreAllocationPolicy>
class SplayTree;
class String;
+class Name;
class Struct;
class Variable;
class RelocInfo;
function ObjectHasOwnProperty(V) {
if (%IsJSProxy(this)) {
var handler = %GetHandler(this);
- return CallTrap1(handler, "hasOwn", DerivedHasOwnTrap, TO_STRING_INLINE(V));
+ return CallTrap1(handler, "hasOwn", DerivedHasOwnTrap, ToName(V));
}
- return %HasLocalProperty(TO_OBJECT_INLINE(this), TO_STRING_INLINE(V));
+ return %HasLocalProperty(TO_OBJECT_INLINE(this), ToName(V));
}
// ECMA-262 - 15.2.4.6
function ObjectPropertyIsEnumerable(V) {
- var P = ToString(V);
+ var P = ToName(V);
if (%IsJSProxy(this)) {
var desc = GetOwnProperty(this, P);
return IS_UNDEFINED(desc) ? false : desc.isEnumerable();
desc.setGet(fun);
desc.setEnumerable(true);
desc.setConfigurable(true);
- DefineOwnProperty(ToObject(receiver), ToString(name), desc, false);
+ DefineOwnProperty(ToObject(receiver), ToName(name), desc, false);
}
if (receiver == null && !IS_UNDETECTABLE(receiver)) {
receiver = %GlobalReceiver(global);
}
- return %LookupAccessor(ToObject(receiver), ToString(name), GETTER);
+ return %LookupAccessor(ToObject(receiver), ToName(name), GETTER);
}
desc.setSet(fun);
desc.setEnumerable(true);
desc.setConfigurable(true);
- DefineOwnProperty(ToObject(receiver), ToString(name), desc, false);
+ DefineOwnProperty(ToObject(receiver), ToName(name), desc, false);
}
if (receiver == null && !IS_UNDETECTABLE(receiver)) {
receiver = %GlobalReceiver(global);
}
- return %LookupAccessor(ToObject(receiver), ToString(name), SETTER);
+ return %LookupAccessor(ToObject(receiver), ToName(name), SETTER);
}
if (%IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var names = CallTrap0(handler, "keys", DerivedKeysTrap);
- return ToStringArray(names, "keys");
+ // TODO(rossberg): filter non-string keys.
+ return ToNameArray(names, "keys");
}
return %LocalKeys(obj);
}
// ES5 section 8.12.1.
function GetOwnProperty(obj, v) {
- var p = ToString(v);
+ var p = ToName(v);
if (%IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var descriptor = CallTrap1(handler, "getOwnPropertyDescriptor", void 0, p);
// GetOwnProperty returns an array indexed by the constants
// defined in macros.py.
// If p is not a property on obj undefined is returned.
- var props = %GetOwnProperty(ToObject(obj), ToString(v));
+ var props = %GetOwnProperty(ToObject(obj), p);
// A false value here means that access checks failed.
if (props === false) return void 0;
// ES5 8.12.9.
function DefineObjectProperty(obj, p, desc, should_throw) {
- var current_or_access = %GetOwnProperty(ToObject(obj), ToString(p));
+ var current_or_access = %GetOwnProperty(ToObject(obj), ToName(p));
// A false value here means that access checks failed.
if (current_or_access === false) return void 0;
// For Harmony proxies
-function ToStringArray(obj, trap) {
+function ToNameArray(obj, trap) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("proxy_non_object_prop_names", [obj, trap]);
}
var array = new $Array(n);
var names = { __proto__: null }; // TODO(rossberg): use sets once ready.
for (var index = 0; index < n; index++) {
- var s = ToString(obj[index]);
+ var s = ToName(obj[index]);
if (%HasLocalProperty(names, s)) {
throw MakeTypeError("proxy_repeated_prop_name", [obj, trap, s]);
}
if (%IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var names = CallTrap0(handler, "getOwnPropertyNames", void 0);
- return ToStringArray(names, "getOwnPropertyNames");
+ return ToNameArray(names, "getOwnPropertyNames");
}
// Find all the indexed properties.
}
}
- // Property names are expected to be unique strings,
+ // Property names are expected to be unique names,
// but interceptors can interfere with that assumption.
if (interceptorInfo != 0) {
var propertySet = { __proto__: null };
var j = 0;
for (var i = 0; i < propertyNames.length; ++i) {
- var name = ToString(propertyNames[i]);
+ var name = ToName(propertyNames[i]);
// We need to check for the exact property value since for intrinsic
// properties like toString if(propertySet["toString"]) will always
// succeed.
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("called_on_non_object", ["Object.defineProperty"]);
}
- var name = ToString(p);
+ var name = ToName(p);
if (%IsJSProxy(obj)) {
// Clone the attributes object for protection.
// TODO(rossberg): not spec'ed yet, so not sure if this should involve
}
-void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
- Label* miss,
- Label* done,
- Register properties,
- Handle<String> name,
- Register r0) {
+void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
+ Label* miss,
+ Label* done,
+ Register properties,
+ Handle<Name> name,
+ Register r0) {
+ ASSERT(name->IsUniqueName());
// If names of slots in range from 1 to kProbes - 1 for the hash value are
// not equal to the name and kProbes-th slot is not used (its name is the
// undefined value), it guarantees the hash table doesn't contain the
__ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset));
__ decl(index);
__ and_(index,
- Immediate(name->Hash() + StringDictionary::GetProbeOffset(i)));
+ Immediate(name->Hash() + NameDictionary::GetProbeOffset(i)));
// Scale the index by multiplying by the entry size.
- ASSERT(StringDictionary::kEntrySize == 3);
+ ASSERT(NameDictionary::kEntrySize == 3);
__ lea(index, Operand(index, index, times_2, 0)); // index *= 3.
Register entity_name = r0;
__ j(equal, done);
// Stop if found the property.
- __ Cmp(entity_name, Handle<String>(name));
+ __ Cmp(entity_name, Handle<Name>(name));
__ j(equal, miss);
- Label the_hole;
+ Label good;
// Check for the hole and skip.
__ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex);
- __ j(equal, &the_hole, Label::kNear);
+ __ j(equal, &good, Label::kNear);
- // Check if the entry name is not an internalized string.
+ // Check if the entry name is not a unique name.
__ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
__ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
Immediate(kIsInternalizedMask));
- __ j(zero, miss);
+ __ j(not_zero, &good, Label::kNear);
+ __ cmpb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
+ Immediate(static_cast<int8_t>(SYMBOL_TYPE)));
+ __ j(not_equal, miss);
- __ bind(&the_hole);
+ __ bind(&good);
}
- StringDictionaryLookupStub stub(properties,
- r0,
- r0,
- StringDictionaryLookupStub::NEGATIVE_LOOKUP);
+ NameDictionaryLookupStub stub(properties, r0, r0, NEGATIVE_LOOKUP);
__ Push(Handle<Object>(name));
__ push(Immediate(name->Hash()));
__ CallStub(&stub);
}
-// Probe the string dictionary in the |elements| register. Jump to the
+// Probe the name dictionary in the |elements| register. Jump to the
// |done| label if a property with the given name is found leaving the
// index into the dictionary in |r1|. Jump to the |miss| label
// otherwise.
-void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
- Label* miss,
- Label* done,
- Register elements,
- Register name,
- Register r0,
- Register r1) {
+void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
+ Label* miss,
+ Label* done,
+ Register elements,
+ Register name,
+ Register r0,
+ Register r1) {
ASSERT(!elements.is(r0));
ASSERT(!elements.is(r1));
ASSERT(!name.is(r0));
ASSERT(!name.is(r1));
- __ AssertString(name);
+ __ AssertName(name);
__ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset));
__ decl(r0);
for (int i = 0; i < kInlinedProbes; i++) {
// Compute the masked index: (hash + i + i * i) & mask.
- __ movl(r1, FieldOperand(name, String::kHashFieldOffset));
- __ shrl(r1, Immediate(String::kHashShift));
+ __ movl(r1, FieldOperand(name, Name::kHashFieldOffset));
+ __ shrl(r1, Immediate(Name::kHashShift));
if (i > 0) {
- __ addl(r1, Immediate(StringDictionary::GetProbeOffset(i)));
+ __ addl(r1, Immediate(NameDictionary::GetProbeOffset(i)));
}
__ and_(r1, r0);
// Scale the index by multiplying by the entry size.
- ASSERT(StringDictionary::kEntrySize == 3);
+ ASSERT(NameDictionary::kEntrySize == 3);
__ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3
// Check if the key is identical to the name.
__ j(equal, done);
}
- StringDictionaryLookupStub stub(elements,
- r0,
- r1,
- POSITIVE_LOOKUP);
+ NameDictionaryLookupStub stub(elements, r0, r1, POSITIVE_LOOKUP);
__ push(name);
- __ movl(r0, FieldOperand(name, String::kHashFieldOffset));
- __ shrl(r0, Immediate(String::kHashShift));
+ __ movl(r0, FieldOperand(name, Name::kHashFieldOffset));
+ __ shrl(r0, Immediate(Name::kHashShift));
__ push(r0);
__ CallStub(&stub);
}
-void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
+void NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
// This stub overrides SometimesSetsUpAFrame() to return false. That means
// we cannot call anything that could cause a GC from this stub.
// Stack frame on entry:
// esp[1 * kPointerSize]: key's hash.
// esp[2 * kPointerSize]: key.
// Registers:
- // dictionary_: StringDictionary to probe.
+ // dictionary_: NameDictionary to probe.
// result_: used as scratch.
// index_: will hold an index of entry if lookup is successful.
// might alias with result_.
// Compute the masked index: (hash + i + i * i) & mask.
__ movq(scratch, Operand(rsp, 2 * kPointerSize));
if (i > 0) {
- __ addl(scratch, Immediate(StringDictionary::GetProbeOffset(i)));
+ __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i)));
}
__ and_(scratch, Operand(rsp, 0));
// Scale the index by multiplying by the entry size.
- ASSERT(StringDictionary::kEntrySize == 3);
+ ASSERT(NameDictionary::kEntrySize == 3);
__ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3.
// Having undefined at this place means the name is not contained.
__ j(equal, &in_dictionary);
if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
- // If we hit a non internalized string key during negative lookup
- // we have to bailout as this key might be equal to the
+ // If we hit a key that is not a unique name during negative
+ // lookup we have to bailout as this key might be equal to the
// key we are looking for.
- // Check if the entry name is not an internalized string.
+ // Check if the entry name is not a unique name.
+ Label cont;
__ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
__ testb(FieldOperand(scratch, Map::kInstanceTypeOffset),
Immediate(kIsInternalizedMask));
- __ j(zero, &maybe_in_dictionary);
+ __ j(not_zero, &cont);
+ __ cmpb(FieldOperand(scratch, Map::kInstanceTypeOffset),
+ Immediate(static_cast<int8_t>(SYMBOL_TYPE)));
+ __ j(not_equal, &maybe_in_dictionary);
+ __ bind(&cont);
}
}
};
-class StringDictionaryLookupStub: public PlatformCodeStub {
+class NameDictionaryLookupStub: public PlatformCodeStub {
public:
enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
- StringDictionaryLookupStub(Register dictionary,
- Register result,
- Register index,
- LookupMode mode)
+ NameDictionaryLookupStub(Register dictionary,
+ Register result,
+ Register index,
+ LookupMode mode)
: dictionary_(dictionary), result_(result), index_(index), mode_(mode) { }
void Generate(MacroAssembler* masm);
Label* miss,
Label* done,
Register properties,
- Handle<String> name,
+ Handle<Name> name,
Register r0);
static void GeneratePositiveLookup(MacroAssembler* masm,
static const int kTotalProbes = 20;
static const int kCapacityOffset =
- StringDictionary::kHeaderSize +
- StringDictionary::kCapacityIndex * kPointerSize;
+ NameDictionary::kHeaderSize +
+ NameDictionary::kCapacityIndex * kPointerSize;
static const int kElementsStartOffset =
- StringDictionary::kHeaderSize +
- StringDictionary::kElementsStartIndex * kPointerSize;
+ NameDictionary::kHeaderSize +
+ NameDictionary::kElementsStartIndex * kPointerSize;
- Major MajorKey() { return StringDictionaryLookup; }
+ Major MajorKey() { return NameDictionaryLookup; }
int MinorKey() {
return DictionaryBits::encode(dictionary_.code()) |
// Generated code falls through if the receiver is a regular non-global
// JS object with slow properties and no interceptors.
-static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
- Register receiver,
- Register r0,
- Register r1,
- Label* miss) {
+static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm,
+ Register receiver,
+ Register r0,
+ Register r1,
+ Label* miss) {
// Register usage:
// receiver: holds the receiver on entry and is unchanged.
// r0: used to hold receiver instance type.
Label done;
// Probe the dictionary.
- StringDictionaryLookupStub::GeneratePositiveLookup(masm,
- miss_label,
- &done,
- elements,
- name,
- r0,
- r1);
+ NameDictionaryLookupStub::GeneratePositiveLookup(masm,
+ miss_label,
+ &done,
+ elements,
+ name,
+ r0,
+ r1);
// If probing finds an entry in the dictionary, r1 contains the
// index into the dictionary. Check that the value is a normal
// property.
__ bind(&done);
const int kElementsStartOffset =
- StringDictionary::kHeaderSize +
- StringDictionary::kElementsStartIndex * kPointerSize;
+ NameDictionary::kHeaderSize +
+ NameDictionary::kElementsStartIndex * kPointerSize;
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
__ Test(Operand(elements, r1, times_pointer_size,
kDetailsOffset - kHeapObjectTag),
Label done;
// Probe the dictionary.
- StringDictionaryLookupStub::GeneratePositiveLookup(masm,
- miss_label,
- &done,
- elements,
- name,
- scratch0,
- scratch1);
+ NameDictionaryLookupStub::GeneratePositiveLookup(masm,
+ miss_label,
+ &done,
+ elements,
+ name,
+ scratch0,
+ scratch1);
// If probing finds an entry in the dictionary, scratch0 contains the
// index into the dictionary. Check that the value is a normal
// property that is not read only.
__ bind(&done);
const int kElementsStartOffset =
- StringDictionary::kHeaderSize +
- StringDictionary::kElementsStartIndex * kPointerSize;
+ NameDictionary::kHeaderSize +
+ NameDictionary::kElementsStartIndex * kPointerSize;
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
const int kTypeAndReadOnlyMask =
(PropertyDetails::TypeField::kMask |
}
-// Checks whether a key is an array index string or an internalized string.
-// Falls through if the key is an internalized string.
-static void GenerateKeyStringCheck(MacroAssembler* masm,
- Register key,
- Register map,
- Register hash,
- Label* index_string,
- Label* not_internalized) {
+// Checks whether a key is an array index string or a unique name.
+// Falls through if the key is a unique name.
+static void GenerateKeyNameCheck(MacroAssembler* masm,
+ Register key,
+ Register map,
+ Register hash,
+ Label* index_string,
+ Label* not_unique) {
// Register use:
// key - holds the key and is unchanged. Assumed to be non-smi.
// Scratch registers:
// map - used to hold the map of the key.
// hash - used to hold the hash of the key.
- __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
- __ j(above_equal, not_internalized);
+ Label unique;
+ __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map);
+ __ j(above, not_unique);
+ STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
+ __ j(equal, &unique);
+
// Is the string an array index, with cached numeric value?
- __ movl(hash, FieldOperand(key, String::kHashFieldOffset));
- __ testl(hash, Immediate(String::kContainsCachedArrayIndexMask));
+ __ movl(hash, FieldOperand(key, Name::kHashFieldOffset));
+ __ testl(hash, Immediate(Name::kContainsCachedArrayIndexMask));
__ j(zero, index_string); // The value in hash is used at jump target.
// Is the string internalized?
STATIC_ASSERT(kInternalizedTag != 0);
__ testb(FieldOperand(map, Map::kInstanceTypeOffset),
Immediate(kIsInternalizedMask));
- __ j(zero, not_internalized);
+ __ j(zero, not_unique);
+
+ __ bind(&unique);
}
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
- Label slow, check_string, index_smi, index_string, property_array_property;
+ Label slow, check_name, index_smi, index_name, property_array_property;
Label probe_dictionary, check_number_dictionary;
// Check that the key is a smi.
- __ JumpIfNotSmi(rax, &check_string);
+ __ JumpIfNotSmi(rax, &check_name);
__ bind(&index_smi);
// Now the key is known to be a smi. This place is also jumped to from below
// where a numeric string is converted to a smi.
__ IncrementCounter(counters->keyed_load_generic_slow(), 1);
GenerateRuntimeGetProperty(masm);
- __ bind(&check_string);
- GenerateKeyStringCheck(masm, rax, rcx, rbx, &index_string, &slow);
+ __ bind(&check_name);
+ GenerateKeyNameCheck(masm, rax, rcx, rbx, &index_name, &slow);
GenerateKeyedLoadReceiverCheck(
masm, rdx, rcx, Map::kHasNamedInterceptor, &slow);
__ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
__ ret(0);
- __ bind(&index_string);
+ __ bind(&index_name);
__ IndexFromHash(rbx, rax);
__ jmp(&index_smi);
}
// Get the receiver of the function from the stack.
__ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
- GenerateStringDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss);
+ GenerateNameDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss);
// rax: elements
// Search the dictionary placing the result in rdi.
__ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
Label do_call, slow_call, slow_load;
- Label check_number_dictionary, check_string, lookup_monomorphic_cache;
- Label index_smi, index_string;
+ Label check_number_dictionary, check_name, lookup_monomorphic_cache;
+ Label index_smi, index_name;
// Check that the key is a smi.
- __ JumpIfNotSmi(rcx, &check_string);
+ __ JumpIfNotSmi(rcx, &check_name);
__ bind(&index_smi);
// Now the key is known to be a smi. This place is also jumped to from below
__ movq(rdi, rax);
__ jmp(&do_call);
- __ bind(&check_string);
- GenerateKeyStringCheck(masm, rcx, rax, rbx, &index_string, &slow_call);
+ __ bind(&check_name);
+ GenerateKeyNameCheck(masm, rcx, rax, rbx, &index_name, &slow_call);
- // The key is known to be an internalized string.
+ // The key is known to be a unique name.
// If the receiver is a regular JS object with slow properties then do
// a quick inline probe of the receiver's dictionary.
// Otherwise do the monomorphic cache probe.
__ bind(&slow_call);
// This branch is taken if:
// - the receiver requires boxing or access check,
- // - the key is neither smi nor internalized string,
+ // - the key is neither smi nor a unique name,
// - the value loaded is not a function,
// - there is hope that the runtime will create a monomorphic call stub
// that will get fetched next time.
__ IncrementCounter(counters->keyed_call_generic_slow(), 1);
GenerateMiss(masm, argc);
- __ bind(&index_string);
+ __ bind(&index_name);
__ IndexFromHash(rbx, rcx);
// Now jump to the place where smi keys are handled.
__ jmp(&index_smi);
// rsp[(argc + 1) * 8] : argument 0 = receiver
// -----------------------------------
- // Check if the name is a string.
+ // Check if the name is really a name.
Label miss;
__ JumpIfSmi(rcx, &miss);
- Condition cond = masm->IsObjectStringType(rcx, rax, rax);
+ Condition cond = masm->IsObjectNameType(rcx, rax, rax);
__ j(NegateCondition(cond), &miss);
CallICBase::GenerateNormal(masm, argc);
__ bind(&miss);
// -----------------------------------
Label miss;
- GenerateStringDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss);
+ GenerateNameDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss);
// rdx: elements
// Search the dictionary placing the result in rax.
Label miss;
- GenerateStringDictionaryReceiverCheck(masm, rdx, rbx, rdi, &miss);
+ GenerateNameDictionaryReceiverCheck(masm, rdx, rbx, rdi, &miss);
GenerateDictionaryStore(masm, &miss, rbx, rcx, rax, r8, r9);
Counters* counters = masm->isolate()->counters();
}
+void MacroAssembler::AssertName(Register object) {
+ if (emit_debug_code()) {
+ testb(object, Immediate(kSmiTagMask));
+ Check(not_equal, "Operand is a smi and not a name");
+ push(object);
+ movq(object, FieldOperand(object, HeapObject::kMapOffset));
+ CmpInstanceType(object, LAST_NAME_TYPE);
+ pop(object);
+ Check(below_equal, "Operand is not a name");
+ }
+}
+
+
void MacroAssembler::AssertRootValue(Register src,
Heap::RootListIndex root_value_index,
const char* message) {
}
+Condition MacroAssembler::IsObjectNameType(Register heap_object,
+ Register map,
+ Register instance_type) {
+ movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
+ movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
+ cmpb(instance_type, Immediate(static_cast<int8_t>(LAST_NAME_TYPE)));
+ return below_equal;
+}
+
+
void MacroAssembler::TryGetFunctionPrototype(Register function,
Register result,
Label* miss,
Register map,
Register instance_type);
+ // Check if the object in register heap_object is a name. Afterwards the
+ // register map contains the object map and the register instance_type
+ // contains the instance_type. The registers map and instance_type can be the
+ // same in which case it contains the instance type afterwards. Either of the
+ // registers map and instance_type can be the same as heap_object.
+ Condition IsObjectNameType(Register heap_object,
+ Register map,
+ Register instance_type);
+
// FCmp compares and pops the two values on top of the FPU stack.
// The flag results are similar to integer cmp, but requires unsigned
// jcc instructions (je, ja, jae, jb, jbe, je, and jz).
// Abort execution if argument is not a string, enabled via --debug-code.
void AssertString(Register object);
+ // Abort execution if argument is not a name, enabled via --debug-code.
+ void AssertName(Register object);
+
// Abort execution if argument is not the root value with the given index,
// enabled via --debug-code.
void AssertRootValue(Register src,
// the property. This function may return false negatives, so miss_label
// must always call a backup property check that is complete.
// This function is safe to call if the receiver has fast properties.
-// Name must be an internalized string and receiver must be a heap object.
+// Name must be unique and receiver must be a heap object.
static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
Label* miss_label,
Register receiver,
- Handle<String> name,
+ Handle<Name> name,
Register r0,
Register r1) {
- ASSERT(name->IsInternalizedString());
+ ASSERT(name->IsUniqueName());
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->negative_lookups(), 1);
__ IncrementCounter(counters->negative_lookups_miss(), 1);
__ j(not_equal, miss_label);
Label done;
- StringDictionaryLookupStub::GenerateNegativeLookup(masm,
- miss_label,
- &done,
- properties,
- name,
- r1);
+ NameDictionaryLookupStub::GenerateNegativeLookup(masm,
+ miss_label,
+ &done,
+ properties,
+ name,
+ r1);
__ bind(&done);
__ DecrementCounter(counters->negative_lookups_miss(), 1);
}
__ JumpIfSmi(receiver, &miss);
// Get the map of the receiver and compute the hash.
- __ movl(scratch, FieldOperand(name, String::kHashFieldOffset));
+ __ movl(scratch, FieldOperand(name, Name::kHashFieldOffset));
// Use only the low 32 bits of the map pointer.
__ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
__ xor_(scratch, Immediate(flags));
ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch);
// Primary miss: Compute hash for secondary probe.
- __ movl(scratch, FieldOperand(name, String::kHashFieldOffset));
+ __ movl(scratch, FieldOperand(name, Name::kHashFieldOffset));
__ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
__ xor_(scratch, Immediate(flags));
__ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
void Compile(MacroAssembler* masm,
Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
LookupResult* lookup,
Register receiver,
Register scratch1,
Register scratch3,
Handle<JSObject> interceptor_holder,
LookupResult* lookup,
- Handle<String> name,
+ Handle<Name> name,
const CallOptimization& optimization,
Label* miss_label) {
ASSERT(optimization.is_constant_call());
Register scratch1,
Register scratch2,
Register scratch3,
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> interceptor_holder,
Label* miss_label) {
Register holder =
Handle<JSObject> object,
int index,
Handle<Map> transition,
- Handle<String> name,
+ Handle<Name> name,
Register receiver_reg,
Register name_reg,
Register scratch1,
// property.
static void GenerateCheckPropertyCell(MacroAssembler* masm,
Handle<GlobalObject> global,
- Handle<String> name,
+ Handle<Name> name,
Register scratch,
Label* miss) {
Handle<JSGlobalPropertyCell> cell =
static void GenerateCheckPropertyCells(MacroAssembler* masm,
Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Register scratch,
Label* miss) {
Handle<JSObject> current = object;
Register holder_reg,
Register scratch1,
Register scratch2,
- Handle<String> name,
+ Handle<Name> name,
int save_at_depth,
Label* miss,
PrototypeCheckType check) {
if (!current->HasFastProperties() &&
!current->IsJSGlobalObject() &&
!current->IsJSGlobalProxy()) {
- if (!name->IsInternalizedString()) {
- name = factory()->InternalizeString(name);
+ if (!name->IsUniqueName()) {
+ ASSERT(name->IsString());
+ name = factory()->InternalizeString(Handle<String>::cast(name));
}
ASSERT(current->property_dictionary()->FindEntry(*name) ==
- StringDictionary::kNotFound);
+ NameDictionary::kNotFound);
GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
scratch1, scratch2);
Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Label* success,
Handle<ExecutableAccessorInfo> callback) {
Label miss;
// Probe the dictionary.
Label probe_done;
- StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
- &miss,
- &probe_done,
- dictionary,
- this->name(),
- scratch2(),
- scratch3());
+ NameDictionaryLookupStub::GeneratePositiveLookup(masm(),
+ &miss,
+ &probe_done,
+ dictionary,
+ this->name(),
+ scratch2(),
+ scratch3());
__ bind(&probe_done);
// If probing finds an entry in the dictionary, scratch3 contains the
// index into the dictionary. Check that the value is the callback.
Register index = scratch3();
const int kElementsStartOffset =
- StringDictionary::kHeaderSize +
- StringDictionary::kElementsStartIndex * kPointerSize;
+ NameDictionary::kHeaderSize +
+ NameDictionary::kElementsStartIndex * kPointerSize;
const int kValueOffset = kElementsStartOffset + kPointerSize;
__ movq(scratch2(),
Operand(dictionary, index, times_pointer_size,
void BaseLoadStubCompiler::NonexistentHandlerFrontend(
Handle<JSObject> object,
Handle<JSObject> last,
- Handle<String> name,
+ Handle<Name> name,
Label* success,
Handle<GlobalObject> global) {
Label miss;
Handle<JSObject> object,
Handle<JSObject> interceptor_holder,
LookupResult* lookup,
- Handle<String> name) {
+ Handle<Name> name) {
ASSERT(interceptor_holder->HasNamedInterceptor());
ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
}
-void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
+void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
if (kind_ == Code::KEYED_CALL_IC) {
__ Cmp(rcx, name);
__ j(not_equal, miss);
void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
Label* miss) {
ASSERT(holder->IsGlobalObject());
Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
Handle<JSObject> holder,
PropertyIndex index,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// rcx : function name
// rsp[0] : return address
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
CheckType check,
Label* success) {
// ----------- S t a t e -------------
Handle<Code> CallStubCompiler::CompileCallConstant(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<String> name,
+ Handle<Name> name,
CheckType check,
Handle<JSFunction> function) {
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
Handle<JSGlobalPropertyCell>::null(),
- function, name);
+ function, Handle<String>::cast(name));
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// rcx : function name
// rsp[0] : return address
Handle<GlobalObject> holder,
Handle<JSGlobalPropertyCell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// rcx : function name
// rsp[0] : return address
// -----------------------------------
if (HasCustomCallGenerator(function)) {
- Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
+ Handle<Code> code = CompileCustomCall(
+ object, holder, cell, function, Handle<String>::cast(name));
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
int index,
Handle<Map> transition,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
Handle<Code> StoreStubCompiler::CompileStoreCallback(
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
- Handle<String> name,
+ Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<JSFunction> setter) {
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> receiver,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
Handle<Code> StoreStubCompiler::CompileStoreGlobal(
Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
int index,
Handle<Map> transition,
- Handle<String> name) {
+ Handle<Name> name) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : key
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
Handle<JSObject> object,
Handle<JSObject> last,
- Handle<String> name,
+ Handle<Name> name,
Handle<GlobalObject> global) {
Label success;
}
-void KeyedLoadStubCompiler::GenerateNameCheck(Handle<String> name,
+void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
Register name_reg,
Label* miss) {
__ Cmp(name_reg, name);
Handle<JSObject> object,
Handle<GlobalObject> global,
Handle<JSGlobalPropertyCell> cell,
- Handle<String> name,
+ Handle<Name> name,
bool is_dont_delete) {
Label success, miss;
// TODO(verwaest): Directly store to rax. Currently we cannot do this, since
Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps,
CodeHandleList* handlers,
- Handle<String> name,
+ Handle<Name> name,
Code::StubType type,
IcCheckType check) {
Label miss;
function TestMap() {
- var map = new Map;
+ var map = new Map
for (var i in symbols) {
map.set(symbols[i], i)
}
}
}
TestMap()
+
+
+
+function TestKeySet(obj) {
+ // Set the even symbols via assignment.
+ for (var i = 0; i < symbols.length; i += 2) {
+ obj[symbols[i]] = i
+ }
+}
+
+
+function TestKeyDefine(obj) {
+ // Set the odd symbols via defineProperty (as non-enumerable).
+ for (var i = 1; i < symbols.length; i += 2) {
+ Object.defineProperty(obj, symbols[i], {value: i, configurable: true})
+ }
+}
+
+
+function TestKeyGet(obj) {
+ var obj2 = Object.create(obj)
+ for (var i in symbols) {
+ assertEquals(i|0, obj[symbols[i]])
+ assertEquals(i|0, obj2[symbols[i]])
+ }
+}
+
+
+function TestKeyHas() {
+ for (var i in symbols) {
+ assertTrue(symbols[i] in obj)
+ assertTrue(Object.hasOwnProperty.call(obj, symbols[i]))
+ }
+}
+
+
+function TestKeyEnum(obj) {
+ // TODO(rossberg): symbols should not show up at all in for-in.
+ var found = [];
+ names: for (var name in obj) {
+ for (var i in symbols) {
+ if (name === symbols[i]) {
+ found[i] = true;
+ continue names;
+ }
+ }
+ }
+ // All even symbols should have been enumerated.
+ for (var i = 0; i < symbols.length; i += 2) {
+ assertTrue(i in found)
+ }
+}
+
+
+function TestKeyKeys(obj) {
+ // TODO(rossberg): symbols should not be returned by Object.keys.
+ assertEquals(symbols.length / 2, Object.keys(obj).length)
+ assertTrue(symbols.length <= Object.getOwnPropertyNames(obj).length)
+}
+
+
+function TestKeyDescriptor(obj) {
+ for (var i in symbols) {
+ var desc = Object.getOwnPropertyDescriptor(obj, symbols[i]);
+ assertEquals(i|0, desc.value)
+ assertTrue(desc.configurable)
+ assertEquals(i % 2 == 0, desc.writable)
+ assertEquals(i % 2 == 0, desc.enumerable)
+ assertEquals(i % 2 == 0,
+ Object.prototype.propertyIsEnumerable.call(obj, symbols[i]))
+ }
+}
+
+
+function TestKeyDelete(obj) {
+ for (var i in symbols) {
+ delete obj[symbols[i]]
+ }
+ for (var i in symbols) {
+ assertEquals(undefined, Object.getOwnPropertyDescriptor(obj, symbols[i]))
+ }
+}
+
+
+var objs = [{}, [], Object.create(null), Object(1), new Map, function(){}]
+
+for (var i in objs) {
+ var obj = objs[i]
+ TestKeySet(obj)
+ TestKeyDefine(obj)
+ TestKeyGet(obj)
+ TestKeyHas(obj)
+ TestKeyEnum(obj)
+ TestKeyKeys(obj)
+ TestKeyDescriptor(obj)
+ TestKeyDelete(obj)
+}