From: rossberg@chromium.org Date: Mon, 4 Mar 2013 15:00:57 +0000 (+0000) Subject: ES6 symbols: Allow symbols as property names X-Git-Tag: upstream/4.7.83~14968 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5c93b18eb2a33ca425f6cee64c6a3913127cbfbb;p=platform%2Fupstream%2Fv8.git ES6 symbols: Allow symbols as property names Since symbols and strings share a common representation, most of this change is about consistently replacing 'String' with 'Name' in all places where property names are expected. In particular, no new logic at all is necessary for maps, property dictionaries, or transitions. :) The only places where an actual case distinction is needed have to do with generated type checks, and with conversions of names to strings (especially in logger and profiler). Left in some TODOs wrt to the API: interceptors and native getters don't accept symbols as property names yet, because that would require extending the external v8.h. (Baseline CL: https://codereview.chromium.org/12296026/) R=verwaest@chromium.org,mstarzinger@chromium.org BUG=v8:2158 Review URL: https://codereview.chromium.org/12330012 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13811 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index fa8e57b..d25406a 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -7425,13 +7425,14 @@ void DirectCEntryStub::GenerateCall(MacroAssembler* masm, } -void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, - Label* miss, - Label* done, - Register receiver, - Register properties, - Handle name, - Register scratch0) { +void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, + Label* miss, + Label* done, + Register receiver, + Register properties, + Handle 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 @@ -7445,10 +7446,10 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, __ 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; @@ -7468,21 +7469,23 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex); // Stop if found the property. - __ cmp(entity_name, Operand(Handle(name))); + __ cmp(entity_name, Operand(Handle(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, @@ -7496,8 +7499,8 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, __ stm(db_w, sp, spill_mask); __ ldr(r0, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); - __ mov(r1, Operand(Handle(name))); - StringDictionaryLookupStub stub(NEGATIVE_LOOKUP); + __ mov(r1, Operand(Handle(name))); + NameDictionaryLookupStub stub(NEGATIVE_LOOKUP); __ CallStub(&stub); __ cmp(r0, Operand::Zero()); __ ldm(ia_w, sp, spill_mask); @@ -7507,23 +7510,23 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, } -// 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)); @@ -7535,20 +7538,20 @@ void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, // 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)); @@ -7573,7 +7576,7 @@ void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, __ Move(r0, elements); __ Move(r1, name); } - StringDictionaryLookupStub stub(POSITIVE_LOOKUP); + NameDictionaryLookupStub stub(POSITIVE_LOOKUP); __ CallStub(&stub); __ cmp(r0, Operand::Zero()); __ mov(scratch2, Operand(r2)); @@ -7584,15 +7587,15 @@ void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, } -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. @@ -7611,7 +7614,7 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { __ 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); @@ -7622,17 +7625,17 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { // 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); @@ -7648,12 +7651,16 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { __ 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); } } diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h index f952756..3e37712 100644 --- a/src/arm/code-stubs-arm.h +++ b/src/arm/code-stubs-arm.h @@ -745,11 +745,11 @@ class FloatingPointHelper : public AllStatic { }; -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); @@ -758,7 +758,7 @@ class StringDictionaryLookupStub: public PlatformCodeStub { Label* done, Register receiver, Register properties, - Handle name, + Handle name, Register scratch0); static void GeneratePositiveLookup(MacroAssembler* masm, @@ -776,14 +776,14 @@ class StringDictionaryLookupStub: public PlatformCodeStub { 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_); diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc index e8d0fab..b4f6f02 100644 --- a/src/arm/ic-arm.cc +++ b/src/arm/ic-arm.cc @@ -64,12 +64,12 @@ static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, // 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. @@ -131,19 +131,19 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, 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)); @@ -180,19 +180,19 @@ static void GenerateDictionaryStore(MacroAssembler* masm, 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 | @@ -303,22 +303,25 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, } -// 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? @@ -326,7 +329,9 @@ static void GenerateKeyStringCheck(MacroAssembler* masm, __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); STATIC_ASSERT(kInternalizedTag != 0); __ tst(hash, Operand(kIsInternalizedMask)); - __ b(eq, not_internalized); + __ b(eq, not_unique); + + __ bind(&unique); } @@ -427,7 +432,7 @@ void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) { // 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. @@ -531,11 +536,11 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { __ 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. @@ -582,10 +587,10 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { __ 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. @@ -613,14 +618,14 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { __ 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); @@ -633,10 +638,10 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { // -- 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); @@ -675,7 +680,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { // ----------------------------------- 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); @@ -918,7 +923,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { // -- 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; @@ -927,7 +932,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 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. @@ -964,8 +969,8 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 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); @@ -979,15 +984,15 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { __ 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; @@ -1004,13 +1009,13 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { __ 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); @@ -1076,7 +1081,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 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); @@ -1547,7 +1552,7 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) { // ----------------------------------- 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(); diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index 326f555..e1d121f 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -1225,6 +1225,16 @@ void MacroAssembler::IsObjectJSStringType(Register object, } +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()); @@ -3196,6 +3206,20 @@ void MacroAssembler::AssertString(Register object) { } +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, diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h index 0826b7d..1fcd7a6 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h @@ -578,6 +578,10 @@ class MacroAssembler: public Assembler { Register scratch, Label* fail); + void IsObjectNameType(Register object, + Register scratch, + Label* fail); + #ifdef ENABLE_DEBUGGER_SUPPORT // --------------------------------------------------------------------------- // Debugger Support @@ -1221,9 +1225,12 @@ class MacroAssembler: public Assembler { 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, diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc index 03aa359..9603410 100644 --- a/src/arm/stub-cache-arm.cc +++ b/src/arm/stub-cache-arm.cc @@ -130,14 +130,14 @@ static void ProbeTable(Isolate* isolate, // 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 name, + Handle 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); @@ -173,13 +173,13 @@ static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, __ 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); } @@ -228,7 +228,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm, __ 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; @@ -443,7 +443,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, Handle object, int index, Handle transition, - Handle name, + Handle name, Register receiver_reg, Register name_reg, Register scratch1, @@ -774,7 +774,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { void Compile(MacroAssembler* masm, Handle object, Handle holder, - Handle name, + Handle name, LookupResult* lookup, Register receiver, Register scratch1, @@ -805,7 +805,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { Register scratch3, Handle interceptor_holder, LookupResult* lookup, - Handle name, + Handle name, const CallOptimization& optimization, Label* miss_label) { ASSERT(optimization.is_constant_call()); @@ -899,7 +899,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { Register scratch1, Register scratch2, Register scratch3, - Handle name, + Handle name, Handle interceptor_holder, Label* miss_label) { Register holder = @@ -956,7 +956,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { // property. static void GenerateCheckPropertyCell(MacroAssembler* masm, Handle global, - Handle name, + Handle name, Register scratch, Label* miss) { Handle cell = @@ -976,7 +976,7 @@ static void GenerateCheckPropertyCell(MacroAssembler* masm, static void GenerateCheckPropertyCells(MacroAssembler* masm, Handle object, Handle holder, - Handle name, + Handle name, Register scratch, Label* miss) { Handle current = object; @@ -1078,7 +1078,7 @@ Register StubCompiler::CheckPrototypes(Handle object, Register holder_reg, Register scratch1, Register scratch2, - Handle name, + Handle name, int save_at_depth, Label* miss, PrototypeCheckType check) { @@ -1110,11 +1110,12 @@ Register StubCompiler::CheckPrototypes(Handle object, if (!current->HasFastProperties() && !current->IsJSGlobalObject() && !current->IsJSGlobalProxy()) { - if (!name->IsInternalizedString()) { - name = factory()->InternalizeString(name); + if (!name->IsUniqueName()) { + ASSERT(name->IsString()); + name = factory()->InternalizeString(Handle::cast(name)); } ASSERT(current->property_dictionary()->FindEntry(*name) == - StringDictionary::kNotFound); + NameDictionary::kNotFound); GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, scratch2); @@ -1198,7 +1199,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( Handle object, Register object_reg, Handle holder, - Handle name, + Handle name, Label* success, Handle callback) { Label miss; @@ -1216,20 +1217,20 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( // 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)); @@ -1244,7 +1245,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( void BaseLoadStubCompiler::NonexistentHandlerFrontend( Handle object, Handle last, - Handle name, + Handle name, Label* success, Handle global) { Label miss; @@ -1301,7 +1302,7 @@ void BaseLoadStubCompiler::GenerateLoadCallback( __ Push(reg, scratch3()); __ mov(scratch3(), Operand(ExternalReference::isolate_address())); __ Push(scratch3(), name()); - __ mov(r0, sp); // r0 = Handle + __ mov(r0, sp); // r0 = Handle const int kApiStackSpace = 1; FrameScope frame_scope(masm(), StackFrame::MANUAL); @@ -1328,7 +1329,7 @@ void BaseLoadStubCompiler::GenerateLoadInterceptor( Handle object, Handle interceptor_holder, LookupResult* lookup, - Handle name) { + Handle name) { ASSERT(interceptor_holder->HasNamedInterceptor()); ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); @@ -1412,7 +1413,7 @@ void BaseLoadStubCompiler::GenerateLoadInterceptor( } -void CallStubCompiler::GenerateNameCheck(Handle name, Label* miss) { +void CallStubCompiler::GenerateNameCheck(Handle name, Label* miss) { if (kind_ == Code::KEYED_CALL_IC) { __ cmp(r2, Operand(name)); __ b(ne, miss); @@ -1422,7 +1423,7 @@ void CallStubCompiler::GenerateNameCheck(Handle name, Label* miss) { void CallStubCompiler::GenerateGlobalReceiverCheck(Handle object, Handle holder, - Handle name, + Handle name, Label* miss) { ASSERT(holder->IsGlobalObject()); @@ -1480,7 +1481,7 @@ void CallStubCompiler::GenerateMissBranch() { Handle CallStubCompiler::CompileCallField(Handle object, Handle holder, PropertyIndex index, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address @@ -2397,7 +2398,7 @@ Handle CallStubCompiler::CompileFastApiCall( void CallStubCompiler::CompileHandlerFrontend(Handle object, Handle holder, - Handle name, + Handle name, CheckType check, Label* success) { // ----------- S t a t e ------------- @@ -2509,13 +2510,13 @@ void CallStubCompiler::CompileHandlerBackend(Handle function) { Handle CallStubCompiler::CompileCallConstant( Handle object, Handle holder, - Handle name, + Handle name, CheckType check, Handle function) { if (HasCustomCallGenerator(function)) { Handle code = CompileCustomCall(object, holder, Handle::null(), - function, name); + function, Handle::cast(name)); // A null handle means bail out to the regular compiler code below. if (!code.is_null()) return code; } @@ -2526,7 +2527,6 @@ Handle CallStubCompiler::CompileCallConstant( __ bind(&success); CompileHandlerBackend(function); - // Return the generated code. return GetCode(function); } @@ -2534,7 +2534,7 @@ Handle CallStubCompiler::CompileCallConstant( Handle CallStubCompiler::CompileCallInterceptor(Handle object, Handle holder, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address @@ -2575,13 +2575,14 @@ Handle CallStubCompiler::CompileCallGlobal( Handle holder, Handle cell, Handle function, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address // ----------------------------------- if (HasCustomCallGenerator(function)) { - Handle code = CompileCustomCall(object, holder, cell, function, name); + Handle code = CompileCustomCall( + object, holder, cell, function, Handle::cast(name)); // A null handle means bail out to the regular compiler code below. if (!code.is_null()) return code; } @@ -2631,7 +2632,7 @@ Handle CallStubCompiler::CompileCallGlobal( Handle StoreStubCompiler::CompileStoreField(Handle object, int index, Handle transition, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : receiver @@ -2659,7 +2660,7 @@ Handle StoreStubCompiler::CompileStoreField(Handle object, Handle StoreStubCompiler::CompileStoreCallback( - Handle name, + Handle name, Handle receiver, Handle holder, Handle callback) { @@ -2743,7 +2744,7 @@ void StoreStubCompiler::GenerateStoreViaSetter( Handle StoreStubCompiler::CompileStoreViaSetter( - Handle name, + Handle name, Handle receiver, Handle holder, Handle setter) { @@ -2772,7 +2773,7 @@ Handle StoreStubCompiler::CompileStoreViaSetter( Handle StoreStubCompiler::CompileStoreInterceptor( Handle receiver, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : receiver @@ -2818,7 +2819,7 @@ Handle StoreStubCompiler::CompileStoreInterceptor( Handle StoreStubCompiler::CompileStoreGlobal( Handle object, Handle cell, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : receiver @@ -2864,7 +2865,7 @@ Handle StoreStubCompiler::CompileStoreGlobal( Handle LoadStubCompiler::CompileLoadNonexistent( Handle object, Handle last, - Handle name, + Handle name, Handle global) { Label success; @@ -2895,7 +2896,7 @@ Register* KeyedLoadStubCompiler::registers() { } -void KeyedLoadStubCompiler::GenerateNameCheck(Handle name, +void KeyedLoadStubCompiler::GenerateNameCheck(Handle name, Register name_reg, Label* miss) { __ cmp(name_reg, Operand(name)); @@ -2944,7 +2945,7 @@ Handle LoadStubCompiler::CompileLoadGlobal( Handle object, Handle global, Handle cell, - Handle name, + Handle name, bool is_dont_delete) { Label success, miss; @@ -3008,7 +3009,7 @@ Handle KeyedLoadStubCompiler::CompileLoadElement( Handle BaseLoadStubCompiler::CompilePolymorphicIC( MapHandleList* receiver_maps, CodeHandleList* handlers, - Handle name, + Handle name, Code::StubType type, IcCheckType check) { Label miss; @@ -3041,7 +3042,7 @@ Handle BaseLoadStubCompiler::CompilePolymorphicIC( Handle KeyedStoreStubCompiler::CompileStoreField(Handle object, int index, Handle transition, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : name diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index fcb1de9..f30cedf 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -2294,7 +2294,7 @@ void Genesis::TransferNamedProperties(Handle from, switch (details.type()) { case FIELD: { HandleScope inner(isolate()); - Handle key = Handle(descs->GetKey(i)); + Handle key = Handle(descs->GetKey(i)); int index = descs->GetFieldIndex(i); Handle value = Handle(from->FastPropertyAt(index), isolate()); @@ -2305,7 +2305,7 @@ void Genesis::TransferNamedProperties(Handle from, } case CONSTANT_FUNCTION: { HandleScope inner(isolate()); - Handle key = Handle(descs->GetKey(i)); + Handle key = Handle(descs->GetKey(i)); Handle fun = Handle(descs->GetConstantFunction(i)); CHECK_NOT_EMPTY_HANDLE(isolate(), @@ -2321,7 +2321,7 @@ void Genesis::TransferNamedProperties(Handle from, HandleScope inner(isolate()); ASSERT(!to->HasFastProperties()); // Add to dictionary. - Handle key = Handle(descs->GetKey(i)); + Handle key = Handle(descs->GetKey(i)); Handle callbacks(descs->GetCallbacksObject(i), isolate()); PropertyDetails d = PropertyDetails(details.attributes(), CALLBACKS, @@ -2341,19 +2341,19 @@ void Genesis::TransferNamedProperties(Handle from, } } } else { - Handle properties = - Handle(from->property_dictionary()); + Handle properties = + Handle(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 key = Handle(String::cast(raw_key)); + Handle key = Handle(Name::cast(raw_key)); Handle value = Handle(properties->ValueAt(i), isolate()); if (value->IsJSGlobalPropertyCell()) { diff --git a/src/code-stubs.h b/src/code-stubs.h index f7a4eaa..62b7af2 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -78,7 +78,7 @@ namespace internal { V(ArrayNArgumentsConstructor) \ V(KeyedStoreElement) \ V(DebuggerStatement) \ - V(StringDictionaryLookup) \ + V(NameDictionaryLookup) \ V(ElementsTransitionAndStore) \ V(TransitionElementsKind) \ V(StoreArrayLiteralElement) \ diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc index 3d5e697..c274b16 100644 --- a/src/cpu-profiler.cc +++ b/src/cpu-profiler.cc @@ -63,7 +63,7 @@ ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator, void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag, const char* prefix, - String* name, + Name* name, Address start) { if (FilterOutCodeCreateEvent(tag)) return; CodeEventsContainer evt_rec; @@ -79,7 +79,7 @@ void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag, void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag, - String* name, + Name* name, String* resource_name, int line_number, Address start, @@ -372,7 +372,7 @@ bool CpuProfiler::HasDetachedProfiles() { } -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); } @@ -386,7 +386,7 @@ void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, - Code* code, String* name) { + Code* code, Name* name) { Isolate* isolate = Isolate::Current(); isolate->cpu_profiler()->processor_->CodeCreateEvent( tag, @@ -402,7 +402,7 @@ void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags 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, @@ -455,7 +455,7 @@ void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) { } -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); } @@ -471,7 +471,7 @@ void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) { } -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); } diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h index 187cbbf..92c3589 100644 --- a/src/cpu-profiler.h +++ b/src/cpu-profiler.h @@ -136,10 +136,10 @@ class ProfilerEventsProcessor : public Thread { // 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); @@ -229,15 +229,15 @@ class CpuProfiler { // 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, @@ -247,9 +247,9 @@ class CpuProfiler { 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)) { diff --git a/src/factory.cc b/src/factory.cc index bb0e85f..83fb1ff 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -70,11 +70,11 @@ Handle Factory::NewFixedDoubleArray(int size, } -Handle Factory::NewStringDictionary(int at_least_space_for) { +Handle 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); } diff --git a/src/factory.h b/src/factory.h index 3651d36..7b8f200 100644 --- a/src/factory.h +++ b/src/factory.h @@ -60,7 +60,7 @@ class Factory { Handle NewUnseededNumberDictionary( int at_least_space_for); - Handle NewStringDictionary(int at_least_space_for); + Handle NewNameDictionary(int at_least_space_for); Handle NewObjectHashSet(int at_least_space_for); diff --git a/src/handles.cc b/src/handles.cc index 7496cc1..6584bdb 100644 --- a/src/handles.cc +++ b/src/handles.cc @@ -260,7 +260,7 @@ Handle ForceDeleteProperty(Handle object, Handle SetPropertyWithInterceptor(Handle object, - Handle key, + Handle key, Handle value, PropertyAttributes attributes, StrictModeFlag strict_mode) { @@ -291,7 +291,7 @@ Handle GetProperty(Isolate* isolate, Handle GetPropertyWithInterceptor(Handle receiver, Handle holder, - Handle name, + Handle name, PropertyAttributes* attributes) { Isolate* isolate = receiver->GetIsolate(); CALL_HEAP_FUNCTION(isolate, @@ -625,7 +625,7 @@ static bool ContainsOnlyValidKeys(Handle array) { 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; } @@ -831,7 +831,7 @@ Handle GetEnumPropertyKeys(Handle object, return ReduceFixedArrayTo(storage, enum_size); } else { - Handle dictionary(object->property_dictionary()); + Handle dictionary(object->property_dictionary()); int length = dictionary->NumberOfElements(); if (length == 0) { @@ -852,7 +852,7 @@ Handle GetEnumPropertyKeys(Handle object, // 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(); } diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc index 9e96685..5f46678 100644 --- a/src/heap-snapshot-generator.cc +++ b/src/heap-snapshot-generator.cc @@ -1320,7 +1320,7 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) { 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()) { @@ -1378,7 +1378,7 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) { } } } 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); @@ -1688,19 +1688,20 @@ void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj, 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, diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h index 77c659a..fe15715 100644 --- a/src/heap-snapshot-generator.h +++ b/src/heap-snapshot-generator.h @@ -512,7 +512,7 @@ class V8HeapExplorer : public HeapEntriesAllocator { 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); diff --git a/src/heap.cc b/src/heap.cc index 7ce9263..4f85705 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -2865,14 +2865,14 @@ bool Heap::CreateInitialObjects() { 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; @@ -4066,9 +4066,9 @@ MaybeObject* Heap::AllocateArgumentsObject(Object* callee, int length) { 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; } @@ -4521,9 +4521,9 @@ MaybeObject* Heap::AllocateGlobalObject(JSFunction* constructor) { 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; @@ -7443,7 +7443,7 @@ const char* GCTracer::CollectorString() { } -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(reinterpret_cast(map)) >> kMapHashShift; @@ -7451,7 +7451,7 @@ int KeyedLookupCache::Hash(Map* map, String* name) { } -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]; @@ -7463,37 +7463,43 @@ int KeyedLookupCache::Lookup(Map* map, String* name) { } -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; } diff --git a/src/heap.h b/src/heap.h index a5ff86e..f79b0ea 100644 --- a/src/heap.h +++ b/src/heap.h @@ -160,7 +160,7 @@ namespace internal { 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) \ @@ -2496,10 +2496,10 @@ class HeapIterator BASE_EMBEDDED { 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(); @@ -2524,7 +2524,7 @@ class KeyedLookupCache { } } - 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. @@ -2538,7 +2538,7 @@ class KeyedLookupCache { struct Key { Map* map; - String* name; + Name* name; }; Key keys_[kLength]; @@ -2558,8 +2558,8 @@ class DescriptorLookupCache { 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]; @@ -2567,9 +2567,9 @@ class DescriptorLookupCache { } // 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; @@ -2592,7 +2592,7 @@ class DescriptorLookupCache { } } - 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(reinterpret_cast(source)) @@ -2606,7 +2606,7 @@ class DescriptorLookupCache { static const int kLength = 64; struct Key { Map* source; - String* name; + Name* name; }; Key keys_[kLength]; diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 1329a3e..0ce8dec 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -7233,14 +7233,14 @@ void ICCompareStub::GenerateMiss(MacroAssembler* masm) { // 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 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, + 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 @@ -7255,10 +7255,10 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, __ 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. @@ -7269,26 +7269,26 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, __ j(equal, done); // Stop if found the property. - __ cmp(entity_name, Handle(name)); + __ cmp(entity_name, Handle(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(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(name))); __ push(Immediate(name->Hash())); __ CallStub(&stub); @@ -7298,23 +7298,23 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, } -// 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 @@ -7325,15 +7325,15 @@ void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, // 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. @@ -7344,13 +7344,10 @@ void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, __ 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); @@ -7360,7 +7357,7 @@ void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, } -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: @@ -7368,7 +7365,7 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { // 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_. @@ -7393,12 +7390,12 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { // 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. @@ -7415,15 +7412,20 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { __ 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(SYMBOL_TYPE)); + __ j(not_equal, &maybe_in_dictionary); + __ bind(&cont); } } diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h index e6bb38a..af1c999 100644 --- a/src/ia32/code-stubs-ia32.h +++ b/src/ia32/code-stubs-ia32.h @@ -320,14 +320,14 @@ class NumberToStringStub: public PlatformCodeStub { }; -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); @@ -336,7 +336,7 @@ class StringDictionaryLookupStub: public PlatformCodeStub { Label* miss, Label* done, Register properties, - Handle name, + Handle name, Register r0); static void GeneratePositiveLookup(MacroAssembler* masm, @@ -354,14 +354,14 @@ class StringDictionaryLookupStub: public PlatformCodeStub { 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()) | diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc index 428d830..5bfa366 100644 --- a/src/ia32/ic-ia32.cc +++ b/src/ia32/ic-ia32.cc @@ -60,11 +60,11 @@ static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, // 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. @@ -127,21 +127,21 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, 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)); @@ -182,21 +182,21 @@ static void GenerateDictionaryStore(MacroAssembler* masm, // 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 | @@ -292,31 +292,36 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, } -// 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); } @@ -403,11 +408,11 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { // -- 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. @@ -458,8 +463,8 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { __ 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); @@ -568,7 +573,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { __ 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); @@ -1016,7 +1021,7 @@ void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) { // 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. @@ -1132,11 +1137,11 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { __ 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 @@ -1195,10 +1200,10 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { __ 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. @@ -1224,14 +1229,14 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { __ 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); @@ -1276,10 +1281,10 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { // -- 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); @@ -1313,7 +1318,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { // ----------------------------------- Label miss; - GenerateStringDictionaryReceiverCheck(masm, edx, eax, ebx, &miss); + GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss); // eax: elements // Search the dictionary placing the result in eax. @@ -1437,7 +1442,7 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) { 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 diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index 587699f..a30f808 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -643,6 +643,16 @@ Condition MacroAssembler::IsObjectStringType(Register heap_object, } +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(LAST_NAME_TYPE)); + return below_equal; +} + + void MacroAssembler::IsObjectJSObjectType(Register heap_object, Register map, Register scratch, @@ -710,6 +720,19 @@ void MacroAssembler::AssertString(Register object) { } +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)); diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index 65899ce..05ad82d 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -423,6 +423,15 @@ class MacroAssembler: public Assembler { 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. @@ -513,6 +522,9 @@ class MacroAssembler: public Assembler { // 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 diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc index 34ce36d..86caecb 100644 --- a/src/ia32/stub-cache-ia32.cc +++ b/src/ia32/stub-cache-ia32.cc @@ -141,14 +141,14 @@ static void ProbeTable(Isolate* isolate, // 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 name, + Handle 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); @@ -177,12 +177,12 @@ static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, __ 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); } @@ -227,7 +227,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm, __ 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 @@ -241,7 +241,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm, 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); @@ -547,7 +547,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { void Compile(MacroAssembler* masm, Handle object, Handle holder, - Handle name, + Handle name, LookupResult* lookup, Register receiver, Register scratch1, @@ -579,7 +579,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { Register scratch3, Handle interceptor_holder, LookupResult* lookup, - Handle name, + Handle name, const CallOptimization& optimization, Label* miss_label) { ASSERT(optimization.is_constant_call()); @@ -672,7 +672,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { Register scratch1, Register scratch2, Register scratch3, - Handle name, + Handle name, Handle interceptor_holder, Label* miss_label) { Register holder = @@ -760,7 +760,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, Handle object, int index, Handle transition, - Handle name, + Handle name, Register receiver_reg, Register name_reg, Register scratch1, @@ -894,7 +894,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, // property. static void GenerateCheckPropertyCell(MacroAssembler* masm, Handle global, - Handle name, + Handle name, Register scratch, Label* miss) { Handle cell = @@ -917,7 +917,7 @@ static void GenerateCheckPropertyCell(MacroAssembler* masm, static void GenerateCheckPropertyCells(MacroAssembler* masm, Handle object, Handle holder, - Handle name, + Handle name, Register scratch, Label* miss) { Handle current = object; @@ -948,7 +948,7 @@ Register StubCompiler::CheckPrototypes(Handle object, Register holder_reg, Register scratch1, Register scratch2, - Handle name, + Handle name, int save_at_depth, Label* miss, PrototypeCheckType check) { @@ -980,11 +980,12 @@ Register StubCompiler::CheckPrototypes(Handle object, if (!current->HasFastProperties() && !current->IsJSGlobalObject() && !current->IsJSGlobalProxy()) { - if (!name->IsInternalizedString()) { - name = factory()->InternalizeString(name); + if (!name->IsUniqueName()) { + ASSERT(name->IsString()); + name = factory()->InternalizeString(Handle::cast(name)); } ASSERT(current->property_dictionary()->FindEntry(*name) == - StringDictionary::kNotFound); + NameDictionary::kNotFound); GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, scratch2); @@ -1070,7 +1071,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( Handle object, Register object_reg, Handle holder, - Handle name, + Handle name, Label* success, Handle callback) { Label miss; @@ -1091,13 +1092,13 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( // 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); @@ -1109,8 +1110,8 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( // 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)); @@ -1129,7 +1130,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( void BaseLoadStubCompiler::NonexistentHandlerFrontend( Handle object, Handle last, - Handle name, + Handle name, Label* success, Handle global) { Label miss; @@ -1222,7 +1223,7 @@ void BaseLoadStubCompiler::GenerateLoadInterceptor( Handle object, Handle interceptor_holder, LookupResult* lookup, - Handle name) { + Handle name) { ASSERT(interceptor_holder->HasNamedInterceptor()); ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); @@ -1318,7 +1319,7 @@ void BaseLoadStubCompiler::GenerateLoadInterceptor( } -void CallStubCompiler::GenerateNameCheck(Handle name, Label* miss) { +void CallStubCompiler::GenerateNameCheck(Handle name, Label* miss) { if (kind_ == Code::KEYED_CALL_IC) { __ cmp(ecx, Immediate(name)); __ j(not_equal, miss); @@ -1328,7 +1329,7 @@ void CallStubCompiler::GenerateNameCheck(Handle name, Label* miss) { void CallStubCompiler::GenerateGlobalReceiverCheck(Handle object, Handle holder, - Handle name, + Handle name, Label* miss) { ASSERT(holder->IsGlobalObject()); @@ -1390,7 +1391,7 @@ void CallStubCompiler::GenerateMissBranch() { Handle CallStubCompiler::CompileCallField(Handle object, Handle holder, PropertyIndex index, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- ecx : name // -- esp[0] : return address @@ -2324,7 +2325,7 @@ Handle CallStubCompiler::CompileFastApiCall( void CallStubCompiler::CompileHandlerFrontend(Handle object, Handle holder, - Handle name, + Handle name, CheckType check, Label* success) { // ----------- S t a t e ------------- @@ -2436,14 +2437,14 @@ void CallStubCompiler::CompileHandlerBackend(Handle function) { Handle CallStubCompiler::CompileCallConstant( Handle object, Handle holder, - Handle name, + Handle name, CheckType check, Handle function) { if (HasCustomCallGenerator(function)) { Handle code = CompileCustomCall(object, holder, Handle::null(), - function, name); + function, Handle::cast(name)); // A null handle means bail out to the regular compiler code below. if (!code.is_null()) return code; } @@ -2461,7 +2462,7 @@ Handle CallStubCompiler::CompileCallConstant( Handle CallStubCompiler::CompileCallInterceptor(Handle object, Handle holder, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- ecx : name // -- esp[0] : return address @@ -2523,7 +2524,7 @@ Handle CallStubCompiler::CompileCallGlobal( Handle holder, Handle cell, Handle function, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- ecx : name // -- esp[0] : return address @@ -2533,7 +2534,8 @@ Handle CallStubCompiler::CompileCallGlobal( // ----------------------------------- if (HasCustomCallGenerator(function)) { - Handle code = CompileCustomCall(object, holder, cell, function, name); + Handle code = CompileCustomCall( + object, holder, cell, function, Handle::cast(name)); // A null handle means bail out to the regular compiler code below. if (!code.is_null()) return code; } @@ -2582,7 +2584,7 @@ Handle CallStubCompiler::CompileCallGlobal( Handle StoreStubCompiler::CompileStoreField(Handle object, int index, Handle transition, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- eax : value // -- ecx : name @@ -2613,7 +2615,7 @@ Handle StoreStubCompiler::CompileStoreField(Handle object, Handle StoreStubCompiler::CompileStoreCallback( - Handle name, + Handle name, Handle receiver, Handle holder, Handle callback) { @@ -2703,7 +2705,7 @@ void StoreStubCompiler::GenerateStoreViaSetter( Handle StoreStubCompiler::CompileStoreViaSetter( - Handle name, + Handle name, Handle receiver, Handle holder, Handle setter) { @@ -2735,7 +2737,7 @@ Handle StoreStubCompiler::CompileStoreViaSetter( Handle StoreStubCompiler::CompileStoreInterceptor( Handle receiver, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- eax : value // -- ecx : name @@ -2782,7 +2784,7 @@ Handle StoreStubCompiler::CompileStoreInterceptor( Handle StoreStubCompiler::CompileStoreGlobal( Handle object, Handle cell, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- eax : value // -- ecx : name @@ -2830,7 +2832,7 @@ Handle StoreStubCompiler::CompileStoreGlobal( Handle KeyedStoreStubCompiler::CompileStoreField(Handle object, int index, Handle transition, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- eax : value // -- ecx : key @@ -2931,7 +2933,7 @@ Handle KeyedStoreStubCompiler::CompileStorePolymorphic( Handle LoadStubCompiler::CompileLoadNonexistent( Handle object, Handle last, - Handle name, + Handle name, Handle global) { Label success; @@ -2962,7 +2964,7 @@ Register* KeyedLoadStubCompiler::registers() { } -void KeyedLoadStubCompiler::GenerateNameCheck(Handle name, +void KeyedLoadStubCompiler::GenerateNameCheck(Handle name, Register name_reg, Label* miss) { __ cmp(name_reg, Immediate(name)); @@ -3011,7 +3013,7 @@ Handle LoadStubCompiler::CompileLoadGlobal( Handle object, Handle global, Handle cell, - Handle name, + Handle name, bool is_dont_delete) { Label success, miss; @@ -3079,7 +3081,7 @@ Handle KeyedLoadStubCompiler::CompileLoadElement( Handle BaseLoadStubCompiler::CompilePolymorphicIC( MapHandleList* receiver_maps, CodeHandleList* handlers, - Handle name, + Handle name, Code::StubType type, IcCheckType check) { Label miss; diff --git a/src/json-stringifier.h b/src/json-stringifier.h index e9121d4..5b41ef5 100644 --- a/src/json-stringifier.h +++ b/src/json-stringifier.h @@ -577,7 +577,10 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( object->elements()->length() == 0) { Handle map(object->map()); for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { - Handle key(map->instance_descriptors()->GetKey(i), isolate_); + Handle name(map->instance_descriptors()->GetKey(i), isolate_); + // TODO(rossberg): Should this throw? + if (!name->IsString()) continue; + Handle key = Handle::cast(name); PropertyDetails details = map->instance_descriptors()->GetDetails(i); if (details.IsDontEnum() || details.IsDeleted()) continue; Handle property; diff --git a/src/log.cc b/src/log.cc index 2ed0141..30ccc6c 100644 --- a/src/log.cc +++ b/src/log.cc @@ -427,6 +427,14 @@ class Logger::NameBuffer { } } + void AppendHex(uint32_t n) { + Vector 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_; } @@ -635,6 +643,8 @@ void Logger::ApiNamedSecurityCheck(Object* key) { SmartArrayPointer 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 { @@ -813,14 +823,19 @@ void Logger::ApiIndexedSecurityCheck(uint32_t index) { 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 class_name = class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); - SmartArrayPointer 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 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, @@ -874,7 +889,7 @@ void Logger::DeleteEventStatic(const char* name, void* object) { 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); @@ -882,33 +897,33 @@ void Logger::CallbackEventInternal(const char* prefix, const char* name, kLogEventsNames[CODE_CREATION_EVENT], kLogEventsNames[CALLBACK_TAG]); msg.AppendAddress(entry_point); - msg.Append(",1,\"%s%s\"", prefix, name); + if (name->IsString()) { + SmartArrayPointer 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 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 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 str = - name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); - CallbackEventInternal("set ", *str, entry_point); + CallbackEventInternal("set ", name, entry_point); } @@ -954,13 +969,19 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, 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()); @@ -979,9 +1000,14 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, 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(); } @@ -1000,14 +1026,20 @@ static const char* ComputeMarker(Code* code) { 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 = @@ -1030,14 +1062,20 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, return; LogMessageBuilder msg(this); - SmartArrayPointer 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 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'); @@ -1051,7 +1089,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, 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(); @@ -1060,7 +1098,13 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, 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); } @@ -1083,18 +1127,20 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, LogMessageBuilder msg(this); SmartArrayPointer name = shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); - SmartArrayPointer 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 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'); @@ -1298,7 +1344,7 @@ void Logger::ResourceEvent(const char* name, const char* tag) { } -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() @@ -1307,9 +1353,13 @@ void Logger::SuspectReadEvent(String* name, Object* obj) { 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(); } @@ -1735,9 +1785,9 @@ void Logger::LogAccessorCallbacks() { 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
(ai->getter()); + Name* name = Name::cast(ai->name()); if (getter_entry != 0) { PROFILE(ISOLATE, GetterCallbackEvent(name, getter_entry)); } diff --git a/src/log.h b/src/log.h index 718dc02..27d517a 100644 --- a/src/log.h +++ b/src/log.h @@ -203,7 +203,7 @@ class Logger { // 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. @@ -224,22 +224,22 @@ class Logger { // ==== 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. @@ -395,7 +395,7 @@ class Logger { // Emits callback event messages. void CallbackEventInternal(const char* prefix, - const char* name, + Name* name, Address entry_point); // Internal configurable move event. diff --git a/src/objects-debug.cc b/src/objects-debug.cc index e583016..226aeb3 100644 --- a/src/objects-debug.cc +++ b/src/objects-debug.cc @@ -922,7 +922,7 @@ void JSObject::IncrementSpillStatistics(SpillInformation* info) { 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(); @@ -1013,10 +1013,10 @@ void JSObject::SpillInformation::Print() { 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; @@ -1035,10 +1035,10 @@ bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) { 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; diff --git a/src/objects-inl.h b/src/objects-inl.h index 374bcbd..21232e1 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -902,13 +902,13 @@ Object* Object::GetElementNoExceptionThrown(uint32_t index) { } -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); } @@ -1493,7 +1493,7 @@ MaybeObject* JSObject::AddFastPropertyUsingMap(Map* map) { bool JSObject::TryTransitionToField(Handle object, - Handle key) { + Handle key) { if (!object->map()->HasTransitionArray()) return false; Handle transitions(object->map()->transitions()); int transition = transitions->Search(*key); @@ -2021,7 +2021,7 @@ void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) { // there are three entries in this array it should be called with low=0 and // high=2. template -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; @@ -2029,7 +2029,7 @@ int BinarySearch(T* array, String* name, int low, int high, int valid_entries) { 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) { @@ -2041,7 +2041,7 @@ int BinarySearch(T* array, String* name, int low, int high, int valid_entries) { 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) { @@ -2058,12 +2058,12 @@ int BinarySearch(T* array, String* name, int low, int high, int valid_entries) { // Perform a linear search in this fixed array. len is the number of entry // indices that are valid. template -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; @@ -2071,7 +2071,7 @@ int LinearSearch(T* array, String* name, int len, int valid_entries) { } 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; } @@ -2081,7 +2081,7 @@ int LinearSearch(T* array, String* name, int len, int valid_entries) { template -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 { @@ -2105,12 +2105,12 @@ int Search(T* array, String* name, int valid_entries) { } -int DescriptorArray::Search(String* name, int valid_descriptors) { +int DescriptorArray::Search(Name* name, int valid_descriptors) { return internal::Search(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; @@ -2127,7 +2127,7 @@ int DescriptorArray::SearchWithCache(String* name, Map* map) { void Map::LookupDescriptor(JSObject* holder, - String* name, + Name* name, LookupResult* result) { DescriptorArray* descriptors = this->instance_descriptors(); int number = descriptors->SearchWithCache(name, this); @@ -2137,7 +2137,7 @@ void Map::LookupDescriptor(JSObject* holder, void Map::LookupTransition(JSObject* holder, - String* name, + Name* name, LookupResult* result) { if (HasTransitionArray()) { TransitionArray* transition_array = transitions(); @@ -2168,9 +2168,9 @@ Object** DescriptorArray::GetDescriptorEndSlot(int descriptor_number) { } -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))); } @@ -2179,7 +2179,7 @@ int DescriptorArray::GetSortedKeyIndex(int descriptor_number) { } -String* DescriptorArray::GetSortedKey(int descriptor_number) { +Name* DescriptorArray::GetSortedKey(int descriptor_number) { return GetKey(GetSortedKeyIndex(descriptor_number)); } @@ -2293,7 +2293,7 @@ void DescriptorArray::Append(Descriptor* desc, 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)); } @@ -2314,7 +2314,7 @@ void DescriptorArray::Append(Descriptor* desc) { 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)); } @@ -2428,12 +2428,12 @@ CAST_ACCESSOR(ExternalString) 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) @@ -2499,10 +2499,16 @@ void Name::set_hash_field(uint32_t value) { } +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); @@ -3231,7 +3237,7 @@ int Map::pre_allocated_property_fields() { 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(map->instance_type()) & ~kIsInternalizedMask; @@ -4013,7 +4019,7 @@ bool Map::CanHaveMoreTransitions() { } -MaybeObject* Map::AddTransition(String* key, +MaybeObject* Map::AddTransition(Name* key, Map* target, SimpleTransitionFlag flag) { if (HasTransitionArray()) return transitions()->CopyInsert(key, target); @@ -5262,9 +5268,9 @@ MaybeObject* JSObject::EnsureWritableFastElements() { } -StringDictionary* JSObject::property_dictionary() { +NameDictionary* JSObject::property_dictionary() { ASSERT(!HasFastProperties()); - return StringDictionary::cast(properties()); + return NameDictionary::cast(properties()); } @@ -5387,6 +5393,11 @@ uint32_t StringHasher::HashSequentialString(const schar* chars, } +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)) { @@ -5406,7 +5417,7 @@ Object* JSReceiver::GetConstructor() { } -bool JSReceiver::HasProperty(String* name) { +bool JSReceiver::HasProperty(Name* name) { if (IsJSProxy()) { return JSProxy::cast(this)->HasPropertyWithHandler(name); } @@ -5414,7 +5425,7 @@ bool JSReceiver::HasProperty(String* name) { } -bool JSReceiver::HasLocalProperty(String* name) { +bool JSReceiver::HasLocalProperty(Name* name) { if (IsJSProxy()) { return JSProxy::cast(this)->HasPropertyWithHandler(name); } @@ -5422,7 +5433,7 @@ bool JSReceiver::HasLocalProperty(String* name) { } -PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) { +PropertyAttributes JSReceiver::GetPropertyAttribute(Name* key) { uint32_t index; if (IsJSObject() && key->AsArrayIndex(&index)) { return GetElementAttribute(index); @@ -5547,7 +5558,7 @@ void Dictionary::SetEntry(int entry, Object* key, Object* value, PropertyDetails details) { - ASSERT(!key->IsString() || + ASSERT(!key->IsName() || details.IsDeleted() || details.dictionary_index() > 0); int index = HashTable::EntryToIndex(entry); @@ -5592,25 +5603,25 @@ MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) { } -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; } diff --git a/src/objects-printer.cc b/src/objects-printer.cc index 32940c4..5c1c7ff 100644 --- a/src/objects-printer.cc +++ b/src/objects-printer.cc @@ -259,7 +259,7 @@ void JSObject::PrintProperties(FILE* out) { 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: { @@ -417,7 +417,7 @@ void JSObject::PrintTransitions(FILE* out) { 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: { @@ -710,6 +710,14 @@ void String::StringPrint(FILE* out) { } +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. @@ -1136,7 +1144,7 @@ void TransitionArray::PrintTransitions(FILE* out) { 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: { diff --git a/src/objects.cc b/src/objects.cc index e05ba05..8b26185 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -130,7 +130,7 @@ Object* Object::ToBoolean() { } -void Object::Lookup(String* name, LookupResult* result) { +void Object::Lookup(Name* name, LookupResult* result) { Object* holder = NULL; if (IsJSReceiver()) { holder = this; @@ -155,7 +155,7 @@ void Object::Lookup(String* name, LookupResult* result) { MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, - String* name, + Name* name, PropertyAttributes* attributes) { LookupResult result(name->GetIsolate()); Lookup(name, &result); @@ -167,7 +167,7 @@ MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, 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 @@ -194,12 +194,15 @@ MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver, 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(fun_obj); if (call_fun == NULL) return isolate->heap()->undefined_value(); HandleScope scope(isolate); JSObject* self = JSObject::cast(receiver); - Handle key(name); + Handle key(String::cast(name)); LOG(isolate, ApiNamedPropertyAccess("load", self, name)); CustomArguments args(isolate, data->data(), self, this); v8::AccessorInfo info(args.end()); @@ -240,7 +243,7 @@ MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver, MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw, - String* name_raw) { + Name* name_raw) { Isolate* isolate = GetIsolate(); HandleScope scope(isolate); Handle receiver(receiver_raw, isolate); @@ -255,11 +258,12 @@ MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw, } -Handle Object::GetProperty(Handle object, Handle name) { +Handle Object::GetProperty(Handle object, Handle 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::cast(object)->GetIsolate() : Isolate::Current(); @@ -332,7 +336,7 @@ MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver, MaybeObject* JSObject::GetPropertyWithFailedAccessCheck( Object* receiver, LookupResult* result, - String* name, + Name* name, PropertyAttributes* attributes) { if (result->IsProperty()) { switch (result->type()) { @@ -392,7 +396,7 @@ MaybeObject* JSObject::GetPropertyWithFailedAccessCheck( PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( Object* receiver, LookupResult* result, - String* name, + Name* name, bool continue_search) { if (result->IsProperty()) { switch (result->type()) { @@ -478,7 +482,7 @@ Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) { Handle JSObject::SetNormalizedProperty(Handle object, - Handle key, + Handle key, Handle value, PropertyDetails details) { CALL_HEAP_FUNCTION(object->GetIsolate(), @@ -487,12 +491,12 @@ Handle JSObject::SetNormalizedProperty(Handle object, } -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(); @@ -505,7 +509,7 @@ MaybeObject* JSObject::SetNormalizedProperty(String* name, 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; } @@ -536,11 +540,11 @@ MaybeObject* JSObject::SetNormalizedProperty(String* name, } -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); @@ -596,7 +600,7 @@ bool JSObject::IsDirty() { Handle Object::GetProperty(Handle object, Handle receiver, LookupResult* result, - Handle key, + Handle key, PropertyAttributes* attributes) { Isolate* isolate = object->IsHeapObject() ? Handle::cast(object)->GetIsolate() @@ -610,7 +614,7 @@ Handle Object::GetProperty(Handle object, 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. @@ -791,7 +795,7 @@ Object* Object::GetDelegate(Isolate* isolate) { 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())); @@ -817,7 +821,7 @@ MaybeObject* Object::GetHash(CreationFlag flag) { 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(); @@ -1553,7 +1557,7 @@ String* JSReceiver::constructor_name() { MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, - String* name, + Name* name, Object* value, int field_index) { if (map()->unused_property_fields() == 0) { @@ -1570,8 +1574,10 @@ MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, } -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); @@ -1587,7 +1593,7 @@ static bool IsIdentifier(UnicodeCache* cache, String* string) { } -MaybeObject* JSObject::AddFastProperty(String* name, +MaybeObject* JSObject::AddFastProperty(Name* name, Object* value, PropertyAttributes attributes, StoreFromKeyed store_mode) { @@ -1596,7 +1602,7 @@ MaybeObject* JSObject::AddFastProperty(String* name, 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(); @@ -1651,7 +1657,7 @@ MaybeObject* JSObject::AddFastProperty(String* name, MaybeObject* JSObject::AddConstantFunctionProperty( - String* name, + Name* name, JSFunction* function, PropertyAttributes attributes) { // Allocate new instance descriptors with (name, function) added @@ -1676,16 +1682,16 @@ MaybeObject* JSObject::AddConstantFunctionProperty( // 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 @@ -1708,12 +1714,12 @@ MaybeObject* JSObject::AddSlowProperty(String* name, { 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, @@ -1729,7 +1735,7 @@ MaybeObject* JSObject::AddProperty(String* name, if (strict_mode == kNonStrictMode) { return value; } else { - Handle args[1] = {Handle(name)}; + Handle args[1] = {Handle(name)}; return isolate->Throw( *FACTORY->NewTypeError("object_not_extensible", HandleVector(args, 1))); @@ -1775,7 +1781,7 @@ MaybeObject* JSObject::AddProperty(String* name, void JSObject::EnqueueChangeRecord(Handle object, const char* type_str, - Handle name, + Handle name, Handle old_value) { Isolate* isolate = object->GetIsolate(); HandleScope scope(isolate); @@ -1808,7 +1814,7 @@ void JSObject::DeliverChangeRecords(Isolate* isolate) { MaybeObject* JSObject::SetPropertyPostInterceptor( - String* name, + Name* name, Object* value, PropertyAttributes attributes, StrictModeFlag strict_mode, @@ -1833,10 +1839,10 @@ MaybeObject* JSObject::SetPropertyPostInterceptor( } -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) { @@ -1851,7 +1857,7 @@ MaybeObject* JSObject::ReplaceSlowProperty(String* name, MaybeObject* JSObject::ConvertTransitionToMapTransition( int transition_index, - String* name, + Name* name, Object* new_value, PropertyAttributes attributes) { Map* old_map = map(); @@ -1897,7 +1903,7 @@ MaybeObject* JSObject::ConvertTransitionToMapTransition( } -MaybeObject* JSObject::ConvertDescriptorToField(String* name, +MaybeObject* JSObject::ConvertDescriptorToField(Name* name, Object* new_value, PropertyAttributes attributes) { if (map()->unused_property_fields() == 0 && @@ -1940,14 +1946,16 @@ MaybeObject* JSObject::ConvertDescriptorToField(String* name, 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 this_handle(this); - Handle name_handle(name); + Handle name_handle(String::cast(name)); Handle value_handle(value, isolate); Handle interceptor(GetNamedInterceptor()); if (!interceptor->setter()->IsUndefined()) { @@ -1983,7 +1991,7 @@ MaybeObject* JSObject::SetPropertyWithInterceptor( Handle JSReceiver::SetProperty(Handle object, - Handle key, + Handle key, Handle value, PropertyAttributes attributes, StrictModeFlag strict_mode) { @@ -1993,7 +2001,7 @@ Handle JSReceiver::SetProperty(Handle object, } -MaybeObject* JSReceiver::SetProperty(String* name, +MaybeObject* JSReceiver::SetProperty(Name* name, Object* value, PropertyAttributes attributes, StrictModeFlag strict_mode, @@ -2008,7 +2016,7 @@ MaybeObject* JSReceiver::SetProperty(String* name, MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, - String* name, + Name* name, Object* value, JSObject* holder, StrictModeFlag strict_mode) { @@ -2046,10 +2054,12 @@ MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, 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(call_obj); if (call_fun == NULL) return value; - Handle key(name); + Handle key(String::cast(name)); LOG(isolate, ApiNamedPropertyAccess("store", this, name)); CustomArguments args(isolate, data->data(), this, JSObject::cast(holder)); v8::AccessorInfo info(args.end()); @@ -2073,7 +2083,7 @@ MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, if (strict_mode == kNonStrictMode) { return value; } - Handle key(name); + Handle key(name); Handle holder_handle(holder, isolate); Handle args[2] = { key, holder_handle }; return isolate->Throw( @@ -2158,7 +2168,7 @@ MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( } MaybeObject* JSObject::SetPropertyViaPrototypes( - String* name, + Name* name, Object* value, PropertyAttributes attributes, StrictModeFlag strict_mode, @@ -2291,15 +2301,17 @@ void Map::AppendCallbackDescriptors(Handle map, 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 entry(AccessorInfo::cast(callbacks.get(i))); - Handle key = - isolate->factory()->InternalizedStringFromString( - Handle(String::cast(entry->name()))); - entry->set_name(*key); + if (!entry->name()->IsUniqueName()) { + Handle key = + isolate->factory()->InternalizedStringFromString( + Handle(String::cast(entry->name()))); + entry->set_name(*key); + } } int nof = map->NumberOfOwnDescriptors(); @@ -2309,7 +2321,7 @@ void Map::AppendCallbackDescriptors(Handle map, // 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()); @@ -2468,8 +2480,7 @@ MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) { } -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(); @@ -2496,7 +2507,7 @@ void JSObject::LocalLookupRealNamedProperty(String* name, } 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); @@ -2517,7 +2528,7 @@ void JSObject::LocalLookupRealNamedProperty(String* name, } -void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) { +void JSObject::LookupRealNamedProperty(Name* name, LookupResult* result) { LocalLookupRealNamedProperty(name, result); if (result->IsFound()) return; @@ -2525,7 +2536,7 @@ void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) { } -void JSObject::LookupRealNamedPropertyInPrototypes(String* name, +void JSObject::LookupRealNamedPropertyInPrototypes(Name* name, LookupResult* result) { Isolate* isolate = GetIsolate(); Heap* heap = isolate->heap(); @@ -2546,7 +2557,7 @@ void JSObject::LookupRealNamedPropertyInPrototypes(String* name, // 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) { @@ -2601,7 +2612,7 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck( MaybeObject* JSReceiver::SetProperty(LookupResult* result, - String* key, + Name* key, Object* value, PropertyAttributes attributes, StrictModeFlag strict_mode, @@ -2616,7 +2627,7 @@ MaybeObject* JSReceiver::SetProperty(LookupResult* result, } -bool JSProxy::HasPropertyWithHandler(String* name_raw) { +bool JSProxy::HasPropertyWithHandler(Name* name_raw) { Isolate* isolate = GetIsolate(); HandleScope scope(isolate); Handle receiver(this, isolate); @@ -2633,7 +2644,7 @@ bool JSProxy::HasPropertyWithHandler(String* name_raw) { MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler( JSReceiver* receiver_raw, - String* name_raw, + Name* name_raw, Object* value_raw, PropertyAttributes attributes, StrictModeFlag strict_mode) { @@ -2653,7 +2664,7 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler( MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler( JSReceiver* receiver_raw, - String* name_raw, + Name* name_raw, Object* value_raw, PropertyAttributes attributes, StrictModeFlag strict_mode, @@ -2661,7 +2672,7 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler( Isolate* isolate = GetIsolate(); Handle proxy(this); Handle receiver(receiver_raw); - Handle name(name_raw); + Handle name(name_raw); Handle value(value_raw, isolate); Handle handler(this->handler(), isolate); // Trap might morph proxy. @@ -2748,7 +2759,7 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler( MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler( - String* name_raw, DeleteMode mode) { + Name* name_raw, DeleteMode mode) { Isolate* isolate = GetIsolate(); HandleScope scope(isolate); Handle receiver(this); @@ -2786,7 +2797,7 @@ MUST_USE_RESULT MaybeObject* JSProxy::DeleteElementWithHandler( MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler( JSReceiver* receiver_raw, - String* name_raw) { + Name* name_raw) { Isolate* isolate = GetIsolate(); HandleScope scope(isolate); Handle proxy(this); @@ -2913,7 +2924,7 @@ void JSObject::AddFastPropertyUsingMap(Handle object, MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, - String* name_raw, + Name* name_raw, Object* value_raw, PropertyAttributes attributes, StrictModeFlag strict_mode, @@ -2927,9 +2938,11 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, // 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); } @@ -2959,7 +2972,7 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, // SetPropertyViaPrototypes might call back into JavaScript. HandleScope scope(isolate); Handle self(this); - Handle name(name_raw); + Handle name(name_raw); Handle value(value_raw, isolate); if (!lookup->IsProperty() && !self->IsJSContextExtensionObject()) { @@ -3092,7 +3105,7 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, // doesn't handle function prototypes correctly. Handle JSObject::SetLocalPropertyIgnoreAttributes( Handle object, - Handle key, + Handle key, Handle value, PropertyAttributes attributes) { CALL_HEAP_FUNCTION( @@ -3103,7 +3116,7 @@ Handle JSObject::SetLocalPropertyIgnoreAttributes( 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 @@ -3143,7 +3156,7 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( // From this point on everything needs to be handlified. HandleScope scope(isolate); Handle self(this); - Handle name(name_raw); + Handle name(name_raw); Handle value(value_raw, isolate); Handle old_value(isolate->heap()->the_hole_value(), isolate); @@ -3239,7 +3252,7 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( JSObject* receiver, - String* name, + Name* name, bool continue_search) { // Check local property, ignore interceptor. LookupResult result(GetIsolate()); @@ -3260,8 +3273,11 @@ PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( 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 @@ -3272,7 +3288,7 @@ PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( Handle interceptor(GetNamedInterceptor()); Handle receiver_handle(receiver); Handle holder_handle(this); - Handle name_handle(name); + Handle name_handle(String::cast(name)); CustomArguments args(isolate, interceptor->data(), receiver, this); v8::AccessorInfo info(args.end()); if (!interceptor->query()->IsUndefined()) { @@ -3311,7 +3327,7 @@ PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver( JSReceiver* receiver, - String* key) { + Name* key) { uint32_t index = 0; if (IsJSObject() && key->AsArrayIndex(&index)) { return JSObject::cast(this)->GetElementAttributeWithReceiver( @@ -3327,7 +3343,7 @@ PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver( PropertyAttributes JSReceiver::GetPropertyAttributeForResult( JSReceiver* receiver, LookupResult* lookup, - String* name, + Name* name, bool continue_search) { // Check access rights if needed. if (IsAccessCheckNeeded()) { @@ -3361,7 +3377,7 @@ PropertyAttributes JSReceiver::GetPropertyAttributeForResult( } -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)) { @@ -3528,7 +3544,7 @@ void NormalizedMapCache::Clear() { void JSObject::UpdateMapCodeCache(Handle object, - Handle name, + Handle name, Handle code) { Isolate* isolate = object->GetIsolate(); CALL_HEAP_FUNCTION_VOID(isolate, @@ -3536,7 +3552,7 @@ void JSObject::UpdateMapCodeCache(Handle object, } -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()); @@ -3582,8 +3598,8 @@ MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, } 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(); @@ -3848,8 +3864,8 @@ MaybeObject* JSProxy::GetIdentityHash(CreationFlag flag) { } -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(); @@ -3882,7 +3898,7 @@ Object* JSObject::GetHiddenProperty(String* key) { Handle JSObject::SetHiddenProperty(Handle obj, - Handle key, + Handle key, Handle value) { CALL_HEAP_FUNCTION(obj->GetIsolate(), obj->SetHiddenProperty(*key, *value), @@ -3890,8 +3906,8 @@ Handle JSObject::SetHiddenProperty(Handle obj, } -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(); @@ -3931,8 +3947,8 @@ MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) { } -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(); @@ -3972,7 +3988,7 @@ MaybeObject* JSObject::GetHiddenPropertiesHashTable( 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) { @@ -4041,7 +4057,7 @@ MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) { 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) { @@ -4066,7 +4082,7 @@ MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) { } -MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, +MaybeObject* JSObject::DeletePropertyPostInterceptor(Name* name, DeleteMode mode) { // Check local property, ignore interceptor. LookupResult result(GetIsolate()); @@ -4083,11 +4099,14 @@ MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, } -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 interceptor(GetNamedInterceptor()); - Handle name_handle(name); + Handle name_handle(String::cast(name)); Handle this_handle(this); if (!interceptor->deleter()->IsUndefined()) { v8::NamedPropertyDeleter deleter = @@ -4230,17 +4249,17 @@ MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { Handle JSObject::DeleteProperty(Handle obj, - Handle prop) { + Handle 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() && @@ -4280,7 +4299,7 @@ MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { // From this point on everything needs to be handlified. HandleScope scope(isolate); Handle self(this); - Handle hname(name); + Handle hname(name); Handle old_value = isolate->factory()->the_hole_value(); bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); @@ -4325,7 +4344,7 @@ MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) { } -MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) { +MaybeObject* JSReceiver::DeleteProperty(Name* name, DeleteMode mode) { if (IsJSProxy()) { return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); } @@ -4557,7 +4576,7 @@ int Map::NumberOfDescribedProperties(DescriptorFlag which, } -int Map::PropertyIndexFor(String* name) { +int Map::PropertyIndexFor(Name* name) { DescriptorArray* descs = instance_descriptors(); int limit = NumberOfOwnDescriptors(); for (int i = 0; i < limit; i++) { @@ -4581,7 +4600,7 @@ int Map::NextFreePropertyIndex() { } -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++) { @@ -4594,8 +4613,8 @@ AccessorDescriptor* Map::FindAccessor(String* name) { 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(); @@ -4639,7 +4658,7 @@ void JSReceiver::LocalLookup( } -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; @@ -4653,7 +4672,7 @@ void JSReceiver::Lookup(String* name, LookupResult* result) { // 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(); @@ -4759,7 +4778,7 @@ MaybeObject* JSObject::DefineElementAccessor(uint32_t index, } -MaybeObject* JSObject::CreateAccessorPairFor(String* name) { +MaybeObject* JSObject::CreateAccessorPairFor(Name* name) { LookupResult result(GetHeap()->isolate()); LocalLookupRealNamedProperty(name, &result); if (result.IsPropertyCallbacks()) { @@ -4778,7 +4797,7 @@ MaybeObject* JSObject::CreateAccessorPairFor(String* name) { } -MaybeObject* JSObject::DefinePropertyAccessor(String* name, +MaybeObject* JSObject::DefinePropertyAccessor(Name* name, Object* getter, Object* setter, PropertyAttributes attributes) { @@ -4815,7 +4834,7 @@ MaybeObject* JSObject::DefinePropertyAccessor(String* name, } -bool JSObject::CanSetCallback(String* name) { +bool JSObject::CanSetCallback(Name* name) { ASSERT(!IsAccessCheckNeeded() || GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); @@ -4877,7 +4896,7 @@ MaybeObject* JSObject::SetElementCallback(uint32_t index, } -MaybeObject* JSObject::SetPropertyCallback(String* name, +MaybeObject* JSObject::SetPropertyCallback(Name* name, Object* structure, PropertyAttributes attributes) { // Normalize object to make this operation simple. @@ -4909,7 +4928,7 @@ MaybeObject* JSObject::SetPropertyCallback(String* name, void JSObject::DefineAccessor(Handle object, - Handle name, + Handle name, Handle getter, Handle setter, PropertyAttributes attributes) { @@ -4918,7 +4937,7 @@ void JSObject::DefineAccessor(Handle object, 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) { @@ -4943,14 +4962,14 @@ MaybeObject* JSObject::DefineAccessor(String* name_raw, 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 self(this); - Handle name(name_raw); + Handle name(name_raw); Handle getter(getter_raw, isolate); Handle setter(setter_raw, isolate); @@ -5021,7 +5040,7 @@ static MaybeObject* TryAccessorTransition(JSObject* self, } -MaybeObject* JSObject::DefineFastAccessor(String* name, +MaybeObject* JSObject::DefineFastAccessor(Name* name, AccessorComponent component, Object* accessor, PropertyAttributes attributes) { @@ -5104,7 +5123,7 @@ MaybeObject* JSObject::DefineFastAccessor(String* name, 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)) { @@ -5124,7 +5143,7 @@ MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { 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(); @@ -5184,7 +5203,7 @@ MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { } -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 @@ -5335,7 +5354,7 @@ MaybeObject* Map::ShareDescriptor(DescriptorArray* descriptors, 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 = @@ -5400,7 +5419,7 @@ MaybeObject* Map::ShareDescriptor(DescriptorArray* descriptors, MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, - String* name, + Name* name, TransitionFlag flag, int descriptor_index) { ASSERT(descriptors->IsSortedNoDuplicates()); @@ -5516,8 +5535,8 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, 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(); @@ -5549,7 +5568,7 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, 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); @@ -5560,8 +5579,8 @@ MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, 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. @@ -5597,11 +5616,11 @@ MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors, 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(); @@ -5632,7 +5651,7 @@ MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors, void Map::UpdateCodeCache(Handle map, - Handle name, + Handle name, Handle code) { Isolate* isolate = map->GetIsolate(); CALL_HEAP_FUNCTION_VOID(isolate, @@ -5640,7 +5659,7 @@ void Map::UpdateCodeCache(Handle map, } -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. @@ -5657,7 +5676,7 @@ MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { } -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); @@ -5676,7 +5695,7 @@ int Map::IndexInCodeCache(Object* name, Code* code) { } -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()); @@ -5879,7 +5898,7 @@ void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { } -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. @@ -5901,7 +5920,7 @@ MaybeObject* CodeCache::Update(String* name, Code* code) { } -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. @@ -5924,7 +5943,7 @@ MaybeObject* CodeCache::UpdateDefaultCache(String* name, Code* code) { 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) { @@ -5961,7 +5980,7 @@ MaybeObject* CodeCache::UpdateDefaultCache(String* name, Code* code) { } -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; @@ -5973,7 +5992,7 @@ MaybeObject* CodeCache::UpdateNormalTypeCache(String* name, Code* code) { } -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 { @@ -5982,7 +6001,7 @@ Object* CodeCache::Lookup(String* name, Code::Flags flags) { } -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) { @@ -5990,7 +6009,7 @@ Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) { // 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; @@ -6001,7 +6020,7 @@ Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) { } -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); @@ -6015,7 +6034,7 @@ int CodeCache::GetIndex(Object* name, Code* code) { 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(); @@ -6031,7 +6050,7 @@ void CodeCache::RemoveByIndex(Object* name, Code* code, int index) { 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(); @@ -6052,10 +6071,10 @@ void CodeCache::RemoveByIndex(Object* name, Code* code, int index) { // 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) { } @@ -6064,7 +6083,7 @@ class CodeCacheHashTableKey : public HashTableKey { 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; @@ -6072,7 +6091,7 @@ class CodeCacheHashTableKey : public HashTableKey { 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; } @@ -6080,7 +6099,7 @@ class CodeCacheHashTableKey : public HashTableKey { 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()); } @@ -6098,14 +6117,14 @@ class CodeCacheHashTableKey : public HashTableKey { } 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(); @@ -6113,7 +6132,7 @@ Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) { } -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); @@ -6136,7 +6155,7 @@ MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) { } -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; @@ -6333,7 +6352,7 @@ MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { 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 @@ -6351,7 +6370,7 @@ MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { 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 @@ -7737,7 +7756,7 @@ void Map::ClearNonLiveTransitions(Heap* heap) { } } 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); @@ -9780,7 +9799,7 @@ MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, } -PropertyType JSObject::GetLocalPropertyType(String* name) { +PropertyType JSObject::GetLocalPropertyType(Name* name) { uint32_t index = 0; if (name->AsArrayIndex(&index)) { return GetLocalElementType(index); @@ -9796,7 +9815,7 @@ PropertyType JSObject::GetLocalElementType(uint32_t index) { } -AccessorPair* JSObject::GetLocalPropertyAccessorPair(String* name) { +AccessorPair* JSObject::GetLocalPropertyAccessorPair(Name* name) { uint32_t index = 0; if (name->AsArrayIndex(&index)) { return GetLocalElementAccessorPair(index); @@ -11096,7 +11115,7 @@ InterceptorInfo* JSObject::GetIndexedInterceptor() { MaybeObject* JSObject::GetPropertyPostInterceptor( Object* receiver, - String* name, + Name* name, PropertyAttributes* attributes) { // Check local property in holder, ignore interceptor. LookupResult result(GetIsolate()); @@ -11114,7 +11133,7 @@ MaybeObject* JSObject::GetPropertyPostInterceptor( MaybeObject* JSObject::GetLocalPropertyPostInterceptor( Object* receiver, - String* name, + Name* name, PropertyAttributes* attributes) { // Check local property in holder, ignore interceptor. LookupResult result(GetIsolate()); @@ -11128,14 +11147,17 @@ MaybeObject* JSObject::GetLocalPropertyPostInterceptor( 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 receiver_handle(receiver, isolate); Handle holder_handle(this); - Handle name_handle(name); + Handle name_handle(String::cast(name)); if (!interceptor->getter()->IsUndefined()) { v8::NamedPropertyGetter getter = @@ -11168,7 +11190,7 @@ MaybeObject* JSObject::GetPropertyWithInterceptor( } -bool JSObject::HasRealNamedProperty(String* key) { +bool JSObject::HasRealNamedProperty(Name* key) { // Check access rights if needed. Isolate* isolate = GetIsolate(); if (IsAccessCheckNeeded()) { @@ -11248,7 +11270,7 @@ bool JSObject::HasRealElementProperty(uint32_t index) { } -bool JSObject::HasRealNamedCallbackProperty(String* key) { +bool JSObject::HasRealNamedCallbackProperty(Name* key) { // Check access rights if needed. Isolate* isolate = GetIsolate(); if (IsAccessCheckNeeded()) { @@ -11406,7 +11428,7 @@ void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) { } else { property_dictionary()->CopyKeysTo(storage, index, - StringDictionary::UNSORTED); + NameDictionary::UNSORTED); } } @@ -11945,15 +11967,15 @@ MaybeObject* HashTable::Allocate(int at_least_space_for, // Find entry for key otherwise return kNotFound. -int StringDictionary::FindEntry(String* key) { - if (!key->IsInternalizedString()) { - return HashTable::FindEntry(key); +int NameDictionary::FindEntry(Name* key) { + if (!key->IsUniqueName()) { + return HashTable::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 @@ -11969,15 +11991,15 @@ int StringDictionary::FindEntry(String* key) { 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; @@ -12104,7 +12126,7 @@ template class HashTable, Object*>; template class HashTable, Object*>; -template class Dictionary; +template class Dictionary; template class Dictionary; @@ -12116,8 +12138,7 @@ template MaybeObject* Dictionary:: template MaybeObject* Dictionary:: Allocate(int at_least_space_for); -template MaybeObject* Dictionary::Allocate( - int); +template MaybeObject* Dictionary::Allocate(int n); template MaybeObject* Dictionary::AtPut( uint32_t, Object*); @@ -12131,7 +12152,7 @@ template Object* Dictionary:: template Object* Dictionary:: SlowReverseLookup(Object* value); -template Object* Dictionary::SlowReverseLookup( +template Object* Dictionary::SlowReverseLookup( Object*); template void Dictionary::CopyKeysTo( @@ -12139,32 +12160,31 @@ template void Dictionary::CopyKeysTo( PropertyAttributes, Dictionary::SortMode); -template Object* Dictionary::DeleteProperty( +template Object* Dictionary::DeleteProperty( int, JSObject::DeleteMode); template Object* Dictionary:: DeleteProperty(int, JSObject::DeleteMode); -template MaybeObject* Dictionary::Shrink( - String*); +template MaybeObject* Dictionary::Shrink(Name* n); template MaybeObject* Dictionary::Shrink( uint32_t); -template void Dictionary::CopyKeysTo( +template void Dictionary::CopyKeysTo( FixedArray*, int, - Dictionary::SortMode); + Dictionary::SortMode); template int -Dictionary::NumberOfElementsFilterAttributes( +Dictionary::NumberOfElementsFilterAttributes( PropertyAttributes); -template MaybeObject* Dictionary::Add( - String*, Object*, PropertyDetails); +template MaybeObject* Dictionary::Add( + Name*, Object*, PropertyDetails); template MaybeObject* -Dictionary::GenerateNewEnumerationIndices(); +Dictionary::GenerateNewEnumerationIndices(); template int Dictionary:: @@ -12182,8 +12202,8 @@ template MaybeObject* Dictionary:: template MaybeObject* Dictionary:: EnsureCapacity(int, uint32_t); -template MaybeObject* Dictionary:: - EnsureCapacity(int, String*); +template MaybeObject* Dictionary:: + EnsureCapacity(int, Name*); template MaybeObject* Dictionary:: AddEntry(uint32_t, Object*, PropertyDetails, uint32_t); @@ -12191,14 +12211,14 @@ template MaybeObject* Dictionary:: template MaybeObject* Dictionary:: AddEntry(uint32_t, Object*, PropertyDetails, uint32_t); -template MaybeObject* Dictionary::AddEntry( - String*, Object*, PropertyDetails, uint32_t); +template MaybeObject* Dictionary::AddEntry( + Name*, Object*, PropertyDetails, uint32_t); template int Dictionary::NumberOfEnumElements(); template -int Dictionary::NumberOfEnumElements(); +int Dictionary::NumberOfEnumElements(); template int HashTable::FindEntry(uint32_t); @@ -12616,7 +12636,7 @@ JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { Handle GlobalObject::EnsurePropertyCell( Handle global, - Handle name) { + Handle name) { Isolate* isolate = global->GetIsolate(); CALL_HEAP_FUNCTION(isolate, global->EnsurePropertyCell(*name), @@ -12624,10 +12644,10 @@ Handle GlobalObject::EnsurePropertyCell( } -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 = @@ -12641,7 +12661,7 @@ MaybeObject* GlobalObject::EnsurePropertyCell(String* name) { 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); @@ -12949,7 +12969,7 @@ void CompilationCacheTable::Remove(Object* value) { } -// 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) { } @@ -13021,8 +13041,8 @@ MaybeObject* Dictionary::Allocate(int at_least_space_for) { } -void StringDictionary::DoGenerateNewEnumerationIndices( - Handle dictionary) { +void NameDictionary::DoGenerateNewEnumerationIndices( + Handle dictionary) { CALL_HEAP_FUNCTION_VOID(dictionary->GetIsolate(), dictionary->GenerateNewEnumerationIndices()); } @@ -13192,8 +13212,8 @@ MaybeObject* Dictionary::AddEntry(Key key, SetNextEnumerationIndex(index + 1); } SetEntry(entry, k, value, details); - ASSERT((Dictionary::KeyAt(entry)->IsNumber() - || Dictionary::KeyAt(entry)->IsString())); + ASSERT((Dictionary::KeyAt(entry)->IsNumber() || + Dictionary::KeyAt(entry)->IsName())); HashTable::ElementAdded(); return this; } @@ -13346,7 +13366,7 @@ void Dictionary::CopyKeysTo( } -FixedArray* StringDictionary::CopyEnumKeysTo(FixedArray* storage) { +FixedArray* NameDictionary::CopyEnumKeysTo(FixedArray* storage) { int length = storage->length(); ASSERT(length >= NumberOfEnumElements()); Heap* heap = GetHeap(); @@ -13430,7 +13450,7 @@ Object* Dictionary::SlowReverseLookup(Object* value) { } -MaybeObject* StringDictionary::TransformPropertiesToFastFor( +MaybeObject* NameDictionary::TransformPropertiesToFastFor( JSObject* obj, int unused_property_fields) { // Make sure we preserve dictionary representation if there are too many // descriptors. @@ -13511,11 +13531,15 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( 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()); diff --git a/src/objects.h b/src/objects.h index bf8c1e8..1ecc3ef 100644 --- a/src/objects.h +++ b/src/objects.h @@ -936,8 +936,6 @@ class MaybeObject BASE_EMBEDDED { 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 @@ -1003,28 +1001,28 @@ class Object : public MaybeObject { // 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 GetProperty(Handle object, Handle key); + static Handle GetProperty(Handle object, Handle key); static Handle GetProperty(Handle object, Handle receiver, LookupResult* result, - Handle key, + Handle 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, @@ -1491,20 +1489,20 @@ class JSReceiver: public HeapObject { static inline JSReceiver* cast(Object* obj); static Handle SetProperty(Handle object, - Handle key, + Handle key, Handle 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, @@ -1512,7 +1510,7 @@ class JSReceiver: public HeapObject { 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. @@ -1533,17 +1531,17 @@ class JSReceiver: public HeapObject { // 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); @@ -1563,9 +1561,9 @@ class JSReceiver: public HeapObject { // 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(); @@ -1573,7 +1571,7 @@ class JSReceiver: public HeapObject { private: PropertyAttributes GetPropertyAttributeForResult(JSReceiver* receiver, LookupResult* result, - String* name, + Name* name, bool continue_search); DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver); @@ -1591,7 +1589,7 @@ class JSObject: public 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). // @@ -1665,34 +1663,34 @@ class JSObject: public JSReceiver { 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, @@ -1700,14 +1698,14 @@ class JSObject: public JSReceiver { static Handle SetLocalPropertyIgnoreAttributes( Handle object, - Handle key, + Handle key, Handle 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 object, - Handle key); + Handle key); inline int LastAddedFieldIndex(); @@ -1718,7 +1716,7 @@ class JSObject: public JSReceiver { // Can cause GC. MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes( - String* key, + Name* key, Object* value, PropertyAttributes attributes); @@ -1733,16 +1731,16 @@ class JSObject: public JSReceiver { // Sets the property value in a normalized object given (key, value, details). // Handles the special representation of JS global objects. static Handle SetNormalizedProperty(Handle object, - Handle key, + Handle key, Handle 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(); @@ -1753,27 +1751,27 @@ class JSObject: public JSReceiver { // 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 object, - Handle name, + Handle name, Handle getter, Handle 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); @@ -1781,11 +1779,11 @@ class JSObject: public JSReceiver { // 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); @@ -1793,19 +1791,19 @@ class JSObject: public JSReceiver { 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 @@ -1828,17 +1826,17 @@ class JSObject: public JSReceiver { // Sets a hidden property on this object. Returns this object if successful, // undefined if called on a detached proxy. static Handle SetHiddenProperty(Handle obj, - Handle key, + Handle key, Handle 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(); @@ -1847,9 +1845,9 @@ class JSObject: public JSReceiver { MUST_USE_RESULT MaybeObject* SetIdentityHash(Smi* hash, CreationFlag flag); static Handle DeleteProperty(Handle obj, - Handle name); + Handle name); // Can cause GC. - MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode); + MUST_USE_RESULT MaybeObject* DeleteProperty(Name* name, DeleteMode mode); static Handle DeleteElement(Handle obj, uint32_t index); MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode); @@ -1893,11 +1891,11 @@ class JSObject: public JSReceiver { 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, @@ -1970,9 +1968,9 @@ class JSObject: public JSReceiver { 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. @@ -1985,12 +1983,12 @@ class JSObject: public JSReceiver { 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). @@ -2017,7 +2015,7 @@ class JSObject: public JSReceiver { // 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); @@ -2028,12 +2026,12 @@ class JSObject: public JSReceiver { // 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); @@ -2057,32 +2055,32 @@ class JSObject: public JSReceiver { // 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, @@ -2109,10 +2107,10 @@ class JSObject: public JSReceiver { MUST_USE_RESULT MaybeObject* NormalizeElements(); static void UpdateMapCodeCache(Handle object, - Handle name, + Handle name, Handle 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. @@ -2249,7 +2247,7 @@ class JSObject: public JSReceiver { // Enqueue change record for Object.observe. May cause GC. static void EnqueueChangeRecord(Handle object, const char* type, - Handle name, + Handle name, Handle old_value); // Deliver change records to observers. May cause GC. @@ -2296,15 +2294,15 @@ class JSObject: public JSReceiver { // 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); @@ -2322,13 +2320,13 @@ class JSObject: public JSReceiver { // 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( @@ -2336,9 +2334,9 @@ class JSObject: public JSReceiver { 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); @@ -2639,7 +2637,7 @@ class DescriptorArray: public FixedArray { 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); @@ -2652,7 +2650,7 @@ class DescriptorArray: public FixedArray { 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); @@ -2682,11 +2680,11 @@ class DescriptorArray: public FixedArray { 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. @@ -2795,11 +2793,11 @@ class DescriptorArray: public FixedArray { enum SearchMode { ALL_ENTRIES, VALID_ENTRIES }; template -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 -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 @@ -3127,11 +3125,11 @@ class MapCacheShape : public BaseShape { // 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 { 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); @@ -3250,29 +3248,29 @@ class Dictionary: public HashTable { }; -class StringDictionaryShape : public BaseShape { +class NameDictionaryShape : public BaseShape { 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 { +class NameDictionary: public Dictionary { public: - static inline StringDictionary* cast(Object* obj) { + static inline NameDictionary* cast(Object* obj) { ASSERT(obj->IsDictionary()); - return reinterpret_cast(obj); + return reinterpret_cast(obj); } // Copies enumerable keys to preallocated fixed array. FixedArray* CopyEnumKeysTo(FixedArray* storage); static void DoGenerateNewEnumerationIndices( - Handle dictionary); + Handle dictionary); // For transforming properties of a JSObject. MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor( @@ -3281,7 +3279,7 @@ class StringDictionary: public Dictionary { // Find entry for key, otherwise return kNotFound. Optimized version of // HashTable::FindEntry. - int FindEntry(String* key); + int FindEntry(Name* key); }; @@ -4993,7 +4991,7 @@ class Map: public HeapObject { 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) @@ -5091,11 +5089,11 @@ class Map: public HeapObject { // 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 @@ -5144,7 +5142,7 @@ class Map: public HeapObject { 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, @@ -5172,7 +5170,7 @@ class Map: public HeapObject { 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(); @@ -5186,7 +5184,7 @@ class Map: public HeapObject { static inline Map* cast(Object* obj); // Locate an accessor in the instance descriptor. - AccessorDescriptor* FindAccessor(String* name); + AccessorDescriptor* FindAccessor(Name* name); // Code cache operations. @@ -5195,9 +5193,9 @@ class Map: public HeapObject { // Update code cache. static void UpdateCodeCache(Handle map, - Handle name, + Handle name, Handle 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. @@ -5207,14 +5205,14 @@ class Map: public HeapObject { static void EnsureDescriptorSlack(Handle 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 @@ -6434,7 +6432,7 @@ class GlobalObject: public JSObject { // 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; } @@ -6442,10 +6440,10 @@ class GlobalObject: public JSObject { // Ensure that the global object has a cell for the given property name. static Handle EnsurePropertyCell( Handle global, - Handle name); + Handle 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); @@ -6896,11 +6894,11 @@ class CodeCache: public Struct { 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 @@ -6923,10 +6921,10 @@ class CodeCache: public Struct { 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. @@ -6964,10 +6962,10 @@ class CodeCacheHashTableShape : public BaseShape { class CodeCacheHashTable: public HashTable { 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); @@ -7254,9 +7252,17 @@ class Name: public HeapObject { // 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; @@ -8180,19 +8186,19 @@ class JSProxy: public JSReceiver { // 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); @@ -8208,14 +8214,14 @@ class JSProxy: public JSReceiver { // 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, @@ -8223,7 +8229,7 @@ class JSProxy: public JSReceiver { MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler( JSReceiver* receiver, - String* name); + Name* name); MUST_USE_RESULT PropertyAttributes GetElementAttributeWithHandler( JSReceiver* receiver, uint32_t index); diff --git a/src/profile-generator-inl.h b/src/profile-generator-inl.h index cbdb6dd..6e7f499 100644 --- a/src/profile-generator-inl.h +++ b/src/profile-generator-inl.h @@ -33,7 +33,7 @@ namespace v8 { namespace internal { -const char* StringsStorage::GetFunctionName(String* name) { +const char* StringsStorage::GetFunctionName(Name* name) { return GetFunctionName(GetName(name)); } diff --git a/src/profile-generator.cc b/src/profile-generator.cc index e5b5194..a51de78 100644 --- a/src/profile-generator.cc +++ b/src/profile-generator.cc @@ -153,14 +153,17 @@ const char* StringsStorage::GetVFormatted(const char* format, va_list args) { } -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 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 ""; } return ""; } @@ -782,7 +785,7 @@ List* CpuProfilesCollection::Profiles(int security_token_id) { CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, - String* name, + Name* name, String* resource_name, int line_number) { CodeEntry* entry = new CodeEntry(tag, @@ -811,7 +814,7 @@ CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, const char* name_prefix, - String* name) { + Name* name) { CodeEntry* entry = new CodeEntry(tag, name_prefix, GetName(name), diff --git a/src/profile-generator.h b/src/profile-generator.h index 8c6c71a..8315f79 100644 --- a/src/profile-generator.h +++ b/src/profile-generator.h @@ -69,9 +69,9 @@ class StringsStorage { 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; @@ -296,7 +296,7 @@ class CpuProfilesCollection { const char* title, double actual_sampling_rate); List* 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) { @@ -308,10 +308,10 @@ class CpuProfilesCollection { 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); @@ -322,7 +322,7 @@ class CpuProfilesCollection { 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) { @@ -395,7 +395,7 @@ class ProfileGenerator { 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); @@ -408,7 +408,7 @@ class ProfileGenerator { INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, const char* name_prefix, - String* name)) { + Name* name)) { return profiles_->NewCodeEntry(tag, name_prefix, name); } diff --git a/src/property.h b/src/property.h index 941b51d..546967a 100644 --- a/src/property.h +++ b/src/property.h @@ -48,15 +48,15 @@ class Descriptor BASE_EMBEDDED { 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_; } @@ -71,25 +71,25 @@ class Descriptor BASE_EMBEDDED { 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, @@ -104,7 +104,7 @@ class Descriptor BASE_EMBEDDED { class FieldDescriptor: public Descriptor { public: - FieldDescriptor(String* key, + FieldDescriptor(Name* key, int field_index, PropertyAttributes attributes, int index = 0) @@ -114,7 +114,7 @@ class FieldDescriptor: public Descriptor { class ConstantFunctionDescriptor: public Descriptor { public: - ConstantFunctionDescriptor(String* key, + ConstantFunctionDescriptor(Name* key, JSFunction* function, PropertyAttributes attributes, int index) @@ -124,7 +124,7 @@ class ConstantFunctionDescriptor: public Descriptor { class CallbacksDescriptor: public Descriptor { public: - CallbacksDescriptor(String* key, + CallbacksDescriptor(Name* key, Object* foreign, PropertyAttributes attributes, int index = 0) diff --git a/src/proxy.js b/src/proxy.js index 53a3572..285d33c 100644 --- a/src/proxy.js +++ b/src/proxy.js @@ -189,6 +189,6 @@ function ProxyEnumerate(proxy) { if (IS_UNDEFINED(handler.enumerate)) { return %Apply(DerivedEnumerateTrap, handler, [], 0, 0) } else { - return ToStringArray(handler.enumerate(), "enumerate") + return ToNameArray(handler.enumerate(), "enumerate") } } diff --git a/src/runtime.cc b/src/runtime.cc index 2215ead..bd18302 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -1049,7 +1049,7 @@ static AccessCheckResult CheckElementAccess( static AccessCheckResult CheckPropertyAccess( JSObject* obj, - String* name, + Name* name, v8::AccessType access_type) { uint32_t index; if (name->AsArrayIndex(&index)) { @@ -1109,7 +1109,7 @@ enum PropertyDescriptorIndices { static MaybeObject* GetOwnProperty(Isolate* isolate, Handle obj, - Handle name) { + Handle 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. @@ -1163,7 +1163,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) { 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); } @@ -2119,7 +2119,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) { } 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(details.attributes() | READ_ONLY), @@ -3898,16 +3898,16 @@ MaybeObject* Runtime::GetObjectProperty(Isolate* isolate, return GetElementOrCharAt(isolate, object, index); } - // Convert the key to a string - possibly by calling back into JavaScript. - Handle name; - if (key->IsString()) { - name = Handle::cast(key); + // Convert the key to a name - possibly by calling back into JavaScript. + Handle name; + if (key->IsName()) { + name = Handle::cast(key); } else { bool has_pending_exception = false; Handle converted = Execution::ToString(key, &has_pending_exception); if (has_pending_exception) return Failure::Exception(); - name = Handle::cast(converted); + name = Handle::cast(converted); } // Check if the name is trivially convertible to an index and get @@ -3931,7 +3931,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) { } -// KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric. +// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric. RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) { NoHandleAllocation ha(isolate); ASSERT(args.length() == 2); @@ -3950,9 +3950,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) { 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(); @@ -3975,9 +3975,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) { } } 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; @@ -3987,7 +3987,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) { } } } else if (FLAG_smi_only_arrays && args.at(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 @@ -4047,7 +4047,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) { 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); @@ -4072,7 +4072,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) { 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); @@ -4137,7 +4137,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) { 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(); @@ -4180,10 +4180,11 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, if (object->IsJSProxy()) { bool has_pending_exception = false; - Handle name = Execution::ToString(key, &has_pending_exception); + Handle 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. @@ -4213,16 +4214,16 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, return *value; } - if (key->IsString()) { + if (key->IsName()) { Handle result; - if (Handle::cast(key)->AsArrayIndex(&index)) { + Handle name = Handle::cast(key); + if (name->AsArrayIndex(&index)) { result = JSObject::SetElement( js_object, index, value, attr, strict_mode, set_mode); } else { - Handle key_string = Handle::cast(key); - key_string->TryFlatten(); + if (name->IsString()) Handle::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; @@ -4268,16 +4269,14 @@ MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate, index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY); } - if (key->IsString()) { - if (Handle::cast(key)->AsArrayIndex(&index)) { + if (key->IsName()) { + Handle name = Handle::cast(key); + if (name->AsArrayIndex(&index)) { return js_object->SetElement( index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY); } else { - Handle key_string = Handle::cast(key); - key_string->TryFlatten(); - return js_object->SetLocalPropertyIgnoreAttributes(*key_string, - *value, - attr); + if (name->IsString()) Handle::cast(name)->TryFlatten(); + return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr); } } @@ -4317,19 +4316,19 @@ MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate, return receiver->DeleteElement(index, JSReceiver::FORCE_DELETION); } - Handle key_string; - if (key->IsString()) { - key_string = Handle::cast(key); + Handle name; + if (key->IsName()) { + name = Handle::cast(key); } else { // Call-back into JavaScript to convert the key to a string. bool has_pending_exception = false; Handle converted = Execution::ToString(key, &has_pending_exception); if (has_pending_exception) return Failure::Exception(); - key_string = Handle::cast(converted); + name = Handle::cast(converted); } - key_string->TryFlatten(); - return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION); + if (name->IsString()) Handle::cast(name)->TryFlatten(); + return receiver->DeleteProperty(*name, JSReceiver::FORCE_DELETION); } @@ -4516,7 +4515,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) { 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) { @@ -4537,7 +4536,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) { 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 @@ -4547,7 +4546,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) { static Object* HasLocalPropertyImplementation(Isolate* isolate, Handle object, - Handle key) { + Handle 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 @@ -4566,7 +4565,7 @@ static Object* HasLocalPropertyImplementation(Isolate* isolate, 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); @@ -4589,7 +4588,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) { HandleScope scope(isolate); return HasLocalPropertyImplementation(isolate, Handle(object), - Handle(key)); + Handle(key)); } else if (obj->IsString() && key_is_array_index) { // Well, there is one exception: Handle [] on strings. String* string = String::cast(obj); @@ -4605,7 +4604,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) { 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(); @@ -4630,7 +4629,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) { 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); @@ -4874,7 +4873,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) { Handle 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()); @@ -4908,6 +4907,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) { 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; @@ -9874,7 +9879,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) { 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(); @@ -9927,7 +9932,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) { static MaybeObject* DebugLookupResultValue(Heap* heap, Object* receiver, - String* name, + Name* name, LookupResult* result, bool* caught_exception) { Object* value; @@ -9999,7 +10004,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) { 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 @@ -10097,7 +10102,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) { 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); @@ -10144,7 +10149,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) { 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); @@ -13253,15 +13258,15 @@ MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap, 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)); diff --git a/src/runtime.js b/src/runtime.js index 6b48734..09b39ff 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -346,7 +346,7 @@ function SHR(y) { // 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); } @@ -356,7 +356,7 @@ function IN(x) { 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)); } @@ -396,7 +396,7 @@ function INSTANCE_OF(F) { // 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; } @@ -563,6 +563,12 @@ function NonStringToString(x) { } +// 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); diff --git a/src/stub-cache.cc b/src/stub-cache.cc index 2bc7355..21ff8eb 100644 --- a/src/stub-cache.cc +++ b/src/stub-cache.cc @@ -56,14 +56,14 @@ void StubCache::Initialize() { } -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 @@ -109,7 +109,7 @@ Handle StubCache::StubHolder(Handle receiver, } -Handle StubCache::FindStub(Handle name, +Handle StubCache::FindStub(Handle name, Handle stub_holder, Code::Kind kind, Code::StubType type, @@ -122,7 +122,7 @@ Handle StubCache::FindStub(Handle name, } -Handle StubCache::FindHandler(Handle name, +Handle StubCache::FindHandler(Handle name, Handle handler_holder, Code::Kind kind, Code::StubType type) { @@ -132,7 +132,7 @@ Handle StubCache::FindHandler(Handle name, Handle StubCache::ComputeMonomorphicIC(Handle receiver, Handle handler, - Handle name) { + Handle name) { Handle ic = FindStub(name, receiver, Code::LOAD_IC, handler->type(), Code::IC_FRAGMENT); if (!ic.is_null()) return ic; @@ -148,7 +148,7 @@ Handle StubCache::ComputeMonomorphicIC(Handle receiver, Handle StubCache::ComputeKeyedMonomorphicIC(Handle receiver, Handle handler, - Handle name) { + Handle name) { Handle ic = FindStub(name, receiver, Code::KEYED_LOAD_IC, handler->type(), Code::IC_FRAGMENT); if (!ic.is_null()) return ic; @@ -162,7 +162,7 @@ Handle StubCache::ComputeKeyedMonomorphicIC(Handle receiver, } -Handle StubCache::ComputeLoadNonexistent(Handle name, +Handle StubCache::ComputeLoadNonexistent(Handle name, Handle 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 @@ -170,7 +170,7 @@ Handle StubCache::ComputeLoadNonexistent(Handle name, // 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 cache_name = factory()->empty_string(); + Handle cache_name = factory()->empty_string(); Handle current; Handle next = receiver; Handle global; @@ -199,7 +199,7 @@ Handle StubCache::ComputeLoadNonexistent(Handle name, } -Handle StubCache::ComputeLoadField(Handle name, +Handle StubCache::ComputeLoadField(Handle name, Handle receiver, Handle holder, PropertyIndex field) { @@ -224,7 +224,7 @@ Handle StubCache::ComputeLoadField(Handle name, Handle StubCache::ComputeLoadCallback( - Handle name, + Handle name, Handle receiver, Handle holder, Handle callback) { @@ -242,7 +242,7 @@ Handle StubCache::ComputeLoadCallback( } -Handle StubCache::ComputeLoadViaGetter(Handle name, +Handle StubCache::ComputeLoadViaGetter(Handle name, Handle receiver, Handle holder, Handle getter) { @@ -259,7 +259,7 @@ Handle StubCache::ComputeLoadViaGetter(Handle name, } -Handle StubCache::ComputeLoadConstant(Handle name, +Handle StubCache::ComputeLoadConstant(Handle name, Handle receiver, Handle holder, Handle value) { @@ -276,7 +276,7 @@ Handle StubCache::ComputeLoadConstant(Handle name, } -Handle StubCache::ComputeLoadInterceptor(Handle name, +Handle StubCache::ComputeLoadInterceptor(Handle name, Handle receiver, Handle holder) { Handle stub_holder = StubHolder(receiver, holder); @@ -292,13 +292,13 @@ Handle StubCache::ComputeLoadInterceptor(Handle name, } -Handle StubCache::ComputeLoadNormal(Handle name, +Handle StubCache::ComputeLoadNormal(Handle name, Handle receiver) { return isolate_->builtins()->LoadIC_Normal(); } -Handle StubCache::ComputeLoadGlobal(Handle name, +Handle StubCache::ComputeLoadGlobal(Handle name, Handle receiver, Handle holder, Handle cell, @@ -316,7 +316,7 @@ Handle StubCache::ComputeLoadGlobal(Handle name, } -Handle StubCache::ComputeKeyedLoadField(Handle name, +Handle StubCache::ComputeKeyedLoadField(Handle name, Handle receiver, Handle holder, PropertyIndex field) { @@ -340,7 +340,7 @@ Handle StubCache::ComputeKeyedLoadField(Handle name, } -Handle StubCache::ComputeKeyedLoadConstant(Handle name, +Handle StubCache::ComputeKeyedLoadConstant(Handle name, Handle receiver, Handle holder, Handle value) { @@ -356,7 +356,7 @@ Handle StubCache::ComputeKeyedLoadConstant(Handle name, } -Handle StubCache::ComputeKeyedLoadInterceptor(Handle name, +Handle StubCache::ComputeKeyedLoadInterceptor(Handle name, Handle receiver, Handle holder) { Handle stub_holder = StubHolder(receiver, holder); @@ -373,7 +373,7 @@ Handle StubCache::ComputeKeyedLoadInterceptor(Handle name, Handle StubCache::ComputeKeyedLoadCallback( - Handle name, + Handle name, Handle receiver, Handle holder, Handle callback) { @@ -390,7 +390,7 @@ Handle StubCache::ComputeKeyedLoadCallback( } -Handle StubCache::ComputeStoreField(Handle name, +Handle StubCache::ComputeStoreField(Handle name, Handle receiver, int field_index, Handle transition, @@ -413,7 +413,7 @@ Handle StubCache::ComputeStoreField(Handle name, Handle StubCache::ComputeKeyedLoadElement(Handle receiver_map) { Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); - Handle name = + Handle name = isolate()->factory()->KeyedLoadElementMonomorphic_string(); Handle probe(receiver_map->FindInCodeCache(*name, flags), isolate_); @@ -440,7 +440,7 @@ Handle StubCache::ComputeKeyedStoreElement( ASSERT(stub_kind == KeyedStoreIC::STORE_NO_TRANSITION || stub_kind == KeyedStoreIC::STORE_AND_GROW_NO_TRANSITION); - Handle name = stub_kind == KeyedStoreIC::STORE_NO_TRANSITION + Handle name = stub_kind == KeyedStoreIC::STORE_NO_TRANSITION ? isolate()->factory()->KeyedStoreElementMonomorphic_string() : isolate()->factory()->KeyedStoreAndGrowElementMonomorphic_string(); @@ -462,7 +462,7 @@ Handle StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) { } -Handle StubCache::ComputeStoreGlobal(Handle name, +Handle StubCache::ComputeStoreGlobal(Handle name, Handle receiver, Handle cell, StrictModeFlag strict_mode) { @@ -480,7 +480,7 @@ Handle StubCache::ComputeStoreGlobal(Handle name, Handle StubCache::ComputeStoreCallback( - Handle name, + Handle name, Handle receiver, Handle holder, Handle callback, @@ -500,7 +500,7 @@ Handle StubCache::ComputeStoreCallback( } -Handle StubCache::ComputeStoreViaSetter(Handle name, +Handle StubCache::ComputeStoreViaSetter(Handle name, Handle receiver, Handle holder, Handle setter, @@ -519,7 +519,7 @@ Handle StubCache::ComputeStoreViaSetter(Handle name, } -Handle StubCache::ComputeStoreInterceptor(Handle name, +Handle StubCache::ComputeStoreInterceptor(Handle name, Handle receiver, StrictModeFlag strict_mode) { Code::Flags flags = Code::ComputeMonomorphicFlags( @@ -534,7 +534,7 @@ Handle StubCache::ComputeStoreInterceptor(Handle name, return code; } -Handle StubCache::ComputeKeyedStoreField(Handle name, +Handle StubCache::ComputeKeyedStoreField(Handle name, Handle receiver, int field_index, Handle transition, @@ -562,7 +562,7 @@ Handle StubCache::ComputeKeyedStoreField(Handle name, Handle StubCache::ComputeCallConstant(int argc, Code::Kind kind, Code::ExtraICState extra_state, - Handle name, + Handle name, Handle object, Handle holder, Handle function) { @@ -614,7 +614,7 @@ Handle StubCache::ComputeCallConstant(int argc, Handle StubCache::ComputeCallField(int argc, Code::Kind kind, Code::ExtraICState extra_state, - Handle name, + Handle name, Handle object, Handle holder, PropertyIndex index) { @@ -654,7 +654,7 @@ Handle StubCache::ComputeCallField(int argc, Handle StubCache::ComputeCallInterceptor(int argc, Code::Kind kind, Code::ExtraICState extra_state, - Handle name, + Handle name, Handle object, Handle holder) { // Compute the check type and the map. @@ -693,7 +693,7 @@ Handle StubCache::ComputeCallInterceptor(int argc, Handle StubCache::ComputeCallGlobal(int argc, Code::Kind kind, Code::ExtraICState extra_state, - Handle name, + Handle name, Handle receiver, Handle holder, Handle cell, @@ -893,7 +893,7 @@ Handle StubCache::ComputeLoadElementPolymorphic( Handle StubCache::ComputePolymorphicIC(MapHandleList* receiver_maps, CodeHandleList* handlers, - Handle name) { + Handle name) { LoadStubCompiler ic_compiler(isolate_); Handle ic = ic_compiler.CompilePolymorphicIC( receiver_maps, handlers, name, Code::NORMAL, PROPERTY); @@ -975,7 +975,7 @@ void StubCache::Clear() { void StubCache::CollectMatchingMaps(SmallMapList* types, - String* name, + Name* name, Code::Flags flags, Handle native_context, Zone* zone) { @@ -1031,9 +1031,14 @@ RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) { v8::AccessorSetter fun = FUNCTION_CAST(setter_address); ASSERT(fun != NULL); ASSERT(callback->IsCompatibleReceiver(recv)); - Handle name = args.at(2); + Handle name = args.at(2); Handle value = args.at(3); HandleScope scope(isolate); + + // TODO(rossberg): Support symbols in the API. + if (name->IsSymbol()) return *value; + Handle str = Handle::cast(name); + LOG(isolate, ApiNamedPropertyAccess("store", recv, *name)); CustomArguments custom_args(isolate, callback->data(), recv, recv); v8::AccessorInfo info(custom_args.end()); @@ -1041,7 +1046,7 @@ RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) { // 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; @@ -1059,7 +1064,7 @@ static const int kAccessorInfoOffsetInInterceptorArgs = 2; * provide any value for the given name. */ RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) { - Handle name_handle = args.at(0); + Handle name_handle = args.at(0); Handle interceptor_info = args.at(1); ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2); ASSERT(args[2]->IsJSObject()); // Receiver. @@ -1067,6 +1072,11 @@ RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) { 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 name = Handle::cast(name_handle); + Address getter_address = v8::ToCData
(interceptor_info->getter()); v8::NamedPropertyGetter getter = FUNCTION_CAST(getter_address); @@ -1081,7 +1091,7 @@ RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) { { // 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()) { @@ -1095,7 +1105,7 @@ RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) { } -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. @@ -1105,7 +1115,7 @@ static MaybeObject* ThrowReferenceError(Isolate* isolate, String* name) { // Throw a reference error. HandleScope scope(isolate); - Handle name_handle(name); + Handle name_handle(name); Handle error = FACTORY->NewReferenceError("not_defined", HandleVector(&name_handle, 1)); @@ -1115,7 +1125,7 @@ static MaybeObject* ThrowReferenceError(Isolate* isolate, String* name) { static MaybeObject* LoadWithInterceptor(Arguments* args, PropertyAttributes* attrs) { - Handle name_handle = args->at(0); + Handle name_handle = args->at(0); Handle interceptor_info = args->at(1); ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2); Handle receiver_handle = args->at(2); @@ -1124,6 +1134,12 @@ static MaybeObject* LoadWithInterceptor(Arguments* args, 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 name = Handle::cast(name_handle); + Address getter_address = v8::ToCData
(interceptor_info->getter()); v8::NamedPropertyGetter getter = FUNCTION_CAST(getter_address); @@ -1138,7 +1154,7 @@ static MaybeObject* LoadWithInterceptor(Arguments* args, { // 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()) { @@ -1171,7 +1187,7 @@ RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) { // 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])); } @@ -1189,7 +1205,7 @@ RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) { 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(args.smi_at(3)); @@ -1371,15 +1387,15 @@ Handle StubCompiler::GetCodeWithFlags(Code::Flags flags, Handle StubCompiler::GetCodeWithFlags(Code::Flags flags, - Handle name) { - return (FLAG_print_code_stubs && !name.is_null()) - ? GetCodeWithFlags(flags, *name->ToCString()) + Handle name) { + return (FLAG_print_code_stubs && !name.is_null() && name->IsString()) + ? GetCodeWithFlags(flags, *Handle::cast(name)->ToCString()) : GetCodeWithFlags(flags, reinterpret_cast(NULL)); } void StubCompiler::LookupPostInterceptor(Handle holder, - Handle name, + Handle name, LookupResult* lookup) { holder->LocalLookupRealNamedProperty(*name, lookup); if (lookup->IsFound()) return; @@ -1394,7 +1410,7 @@ void StubCompiler::LookupPostInterceptor(Handle holder, Register BaseLoadStubCompiler::HandlerFrontendHeader(Handle object, Register object_reg, Handle holder, - Handle name, + Handle name, Label* miss) { // Check the prototype chain. return CheckPrototypes(object, object_reg, holder, @@ -1406,7 +1422,7 @@ Register BaseLoadStubCompiler::HandlerFrontendHeader(Handle object, Register BaseLoadStubCompiler::HandlerFrontend(Handle object, Register object_reg, Handle holder, - Handle name, + Handle name, Label* success) { Label miss; @@ -1419,7 +1435,7 @@ Register BaseLoadStubCompiler::HandlerFrontend(Handle object, Handle BaseLoadStubCompiler::CompileLoadField(Handle object, Handle holder, - Handle name, + Handle name, PropertyIndex field) { Label miss; @@ -1439,7 +1455,7 @@ Handle BaseLoadStubCompiler::CompileLoadField(Handle object, Handle BaseLoadStubCompiler::CompileLoadConstant( Handle object, Handle holder, - Handle name, + Handle name, Handle value) { Label success; HandlerFrontend(object, receiver(), holder, name, &success); @@ -1454,7 +1470,7 @@ Handle BaseLoadStubCompiler::CompileLoadConstant( Handle BaseLoadStubCompiler::CompileLoadCallback( Handle object, Handle holder, - Handle name, + Handle name, Handle callback) { Label success; @@ -1471,7 +1487,7 @@ Handle BaseLoadStubCompiler::CompileLoadCallback( Handle BaseLoadStubCompiler::CompileLoadInterceptor( Handle object, Handle holder, - Handle name) { + Handle name) { Label success; LookupResult lookup(isolate()); @@ -1491,7 +1507,7 @@ Handle BaseLoadStubCompiler::CompileLoadInterceptor( void BaseLoadStubCompiler::GenerateLoadPostInterceptor( Register interceptor_reg, Handle interceptor_holder, - Handle name, + Handle name, LookupResult* lookup) { Label success; Handle holder(lookup->holder()); @@ -1529,7 +1545,7 @@ void BaseLoadStubCompiler::GenerateLoadPostInterceptor( Handle BaseLoadStubCompiler::CompileMonomorphicIC( Handle receiver_map, Handle handler, - Handle name) { + Handle name) { MapHandleList receiver_maps(1); receiver_maps.Add(receiver_map); CodeHandleList handlers(1); @@ -1542,7 +1558,7 @@ Handle BaseLoadStubCompiler::CompileMonomorphicIC( Handle LoadStubCompiler::CompileLoadViaGetter( Handle object, Handle holder, - Handle name, + Handle name, Handle getter) { Label success; HandlerFrontend(object, receiver(), holder, name, &success); @@ -1558,19 +1574,19 @@ Handle LoadStubCompiler::CompileLoadViaGetter( #undef __ -void LoadStubCompiler::JitEvent(Handle name, Handle code) { +void LoadStubCompiler::JitEvent(Handle name, Handle code) { GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); } -void KeyedLoadStubCompiler::JitEvent(Handle name, Handle code) { +void KeyedLoadStubCompiler::JitEvent(Handle name, Handle code) { GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); } Handle BaseLoadStubCompiler::GetCode(Code::IcFragment fragment, Code::StubType type, - Handle name, + Handle name, InlineCacheState state) { Code::Flags flags = Code::ComputeFlags(kind(), state, fragment, type); Handle code = GetCodeWithFlags(flags, name); @@ -1609,7 +1625,7 @@ void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps, Handle StoreStubCompiler::GetCode(Code::StubType type, - Handle name) { + Handle name) { Code::Flags flags = Code::ComputeMonomorphicFlags( Code::STORE_IC, strict_mode_, type); Handle code = GetCodeWithFlags(flags, name); @@ -1620,7 +1636,7 @@ Handle StoreStubCompiler::GetCode(Code::StubType type, Handle KeyedStoreStubCompiler::GetCode(Code::StubType type, - Handle name, + Handle name, InlineCacheState state) { Code::ExtraICState extra_state = Code::ComputeExtraICState(grow_mode_, strict_mode_); @@ -1742,7 +1758,7 @@ Handle CallStubCompiler::CompileCustomCall( Handle CallStubCompiler::GetCode(Code::StubType type, - Handle name) { + Handle name) { int argc = arguments_.immediate(); Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, extra_state_, diff --git a/src/stub-cache.h b/src/stub-cache.h index 5e3fbfc..4155696 100644 --- a/src/stub-cache.h +++ b/src/stub-cache.h @@ -67,7 +67,7 @@ class SCTableReference { class StubCache { public: struct Entry { - String* key; + Name* key; Code* value; Map* map; }; @@ -77,57 +77,57 @@ class StubCache { Handle StubHolder(Handle receiver, Handle holder); - Handle FindStub(Handle name, + Handle FindStub(Handle name, Handle stub_holder, Code::Kind kind, Code::StubType type, Code::IcFragment fragment); - Handle FindHandler(Handle name, + Handle FindHandler(Handle name, Handle stub_holder, Code::Kind kind, Code::StubType type); Handle ComputeMonomorphicIC(Handle receiver, Handle handler, - Handle name); + Handle name); Handle ComputeKeyedMonomorphicIC(Handle receiver, Handle handler, - Handle name); + Handle name); // Computes the right stub matching. Inserts the result in the // cache before returning. This might compile a stub if needed. - Handle ComputeLoadNonexistent(Handle name, + Handle ComputeLoadNonexistent(Handle name, Handle object); - Handle ComputeLoadField(Handle name, + Handle ComputeLoadField(Handle name, Handle object, Handle holder, PropertyIndex field_index); - Handle ComputeLoadCallback(Handle name, + Handle ComputeLoadCallback(Handle name, Handle object, Handle holder, Handle callback); - Handle ComputeLoadViaGetter(Handle name, + Handle ComputeLoadViaGetter(Handle name, Handle object, Handle holder, Handle getter); - Handle ComputeLoadConstant(Handle name, + Handle ComputeLoadConstant(Handle name, Handle object, Handle holder, Handle value); - Handle ComputeLoadInterceptor(Handle name, + Handle ComputeLoadInterceptor(Handle name, Handle object, Handle holder); - Handle ComputeLoadNormal(Handle name, + Handle ComputeLoadNormal(Handle name, Handle object); - Handle ComputeLoadGlobal(Handle name, + Handle ComputeLoadGlobal(Handle name, Handle object, Handle holder, Handle cell, @@ -135,29 +135,29 @@ class StubCache { // --- - Handle ComputeKeyedLoadField(Handle name, + Handle ComputeKeyedLoadField(Handle name, Handle object, Handle holder, PropertyIndex field_index); Handle ComputeKeyedLoadCallback( - Handle name, + Handle name, Handle object, Handle holder, Handle callback); - Handle ComputeKeyedLoadConstant(Handle name, + Handle ComputeKeyedLoadConstant(Handle name, Handle object, Handle holder, Handle value); - Handle ComputeKeyedLoadInterceptor(Handle name, + Handle ComputeKeyedLoadInterceptor(Handle name, Handle object, Handle holder); // --- - Handle ComputeStoreField(Handle name, + Handle ComputeStoreField(Handle name, Handle object, int field_index, Handle transition, @@ -165,30 +165,30 @@ class StubCache { Handle ComputeStoreNormal(StrictModeFlag strict_mode); - Handle ComputeStoreGlobal(Handle name, + Handle ComputeStoreGlobal(Handle name, Handle object, Handle cell, StrictModeFlag strict_mode); - Handle ComputeStoreCallback(Handle name, + Handle ComputeStoreCallback(Handle name, Handle object, Handle holder, Handle callback, StrictModeFlag strict_mode); - Handle ComputeStoreViaSetter(Handle name, + Handle ComputeStoreViaSetter(Handle name, Handle object, Handle holder, Handle setter, StrictModeFlag strict_mode); - Handle ComputeStoreInterceptor(Handle name, + Handle ComputeStoreInterceptor(Handle name, Handle object, StrictModeFlag strict_mode); // --- - Handle ComputeKeyedStoreField(Handle name, + Handle ComputeKeyedStoreField(Handle name, Handle object, int field_index, Handle transition, @@ -206,7 +206,7 @@ class StubCache { Handle ComputeCallField(int argc, Code::Kind, Code::ExtraICState extra_state, - Handle name, + Handle name, Handle object, Handle holder, PropertyIndex index); @@ -214,7 +214,7 @@ class StubCache { Handle ComputeCallConstant(int argc, Code::Kind, Code::ExtraICState extra_state, - Handle name, + Handle name, Handle object, Handle holder, Handle function); @@ -222,14 +222,14 @@ class StubCache { Handle ComputeCallInterceptor(int argc, Code::Kind, Code::ExtraICState extra_state, - Handle name, + Handle name, Handle object, Handle holder); Handle ComputeCallGlobal(int argc, Code::Kind, Code::ExtraICState extra_state, - Handle name, + Handle name, Handle object, Handle holder, Handle cell, @@ -268,7 +268,7 @@ class StubCache { Handle ComputePolymorphicIC(MapHandleList* receiver_maps, CodeHandleList* handlers, - Handle name); + Handle name); // Finds the Code object stored in the Heap::non_monomorphic_cache(). Code* FindCallInitialize(int argc, RelocInfo::Mode mode, Code::Kind kind); @@ -280,14 +280,14 @@ class StubCache { #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 native_context, Zone* zone); @@ -358,12 +358,12 @@ class StubCache { // 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(); @@ -384,25 +384,25 @@ class StubCache { // 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(reinterpret_cast(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(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( reinterpret_cast
(table) + offset * multiplier); } @@ -512,7 +512,7 @@ class StubCompiler BASE_EMBEDDED { Handle object, int index, Handle transition, - Handle name, + Handle name, Register receiver_reg, Register name_reg, Register scratch1, @@ -545,7 +545,7 @@ class StubCompiler BASE_EMBEDDED { Register holder_reg, Register scratch1, Register scratch2, - Handle name, + Handle name, Label* miss, PrototypeCheckType check = CHECK_ALL_MAPS) { return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1, @@ -558,7 +558,7 @@ class StubCompiler BASE_EMBEDDED { Register holder_reg, Register scratch1, Register scratch2, - Handle name, + Handle name, int save_at_depth, Label* miss, PrototypeCheckType check = CHECK_ALL_MAPS); @@ -566,13 +566,13 @@ class StubCompiler BASE_EMBEDDED { protected: Handle GetCodeWithFlags(Code::Flags flags, const char* name); - Handle GetCodeWithFlags(Code::Flags flags, Handle name); + Handle GetCodeWithFlags(Code::Flags flags, Handle name); MacroAssembler* masm() { return &masm_; } void set_failure(Failure* failure) { failure_ = failure; } static void LookupPostInterceptor(Handle holder, - Handle name, + Handle name, LookupResult* lookup); Isolate* isolate() { return isolate_; } @@ -599,29 +599,29 @@ class BaseLoadStubCompiler: public StubCompiler { Handle CompileLoadField(Handle object, Handle holder, - Handle name, + Handle name, PropertyIndex index); Handle CompileLoadCallback(Handle object, Handle holder, - Handle name, + Handle name, Handle callback); Handle CompileLoadConstant(Handle object, Handle holder, - Handle name, + Handle name, Handle value); Handle CompileLoadInterceptor(Handle object, Handle holder, - Handle name); + Handle name); Handle CompileMonomorphicIC(Handle receiver_map, Handle handler, - Handle name); + Handle name); Handle CompilePolymorphicIC(MapHandleList* receiver_maps, CodeHandleList* handlers, - Handle name, + Handle name, Code::StubType type, IcCheckType check); @@ -629,24 +629,24 @@ class BaseLoadStubCompiler: public StubCompiler { Register HandlerFrontendHeader(Handle object, Register object_reg, Handle holder, - Handle name, + Handle name, Label* success); void HandlerFrontendFooter(Label* success, Label* miss); Register HandlerFrontend(Handle object, Register object_reg, Handle holder, - Handle name, + Handle name, Label* success); Register CallbackHandlerFrontend(Handle object, Register object_reg, Handle holder, - Handle name, + Handle name, Label* success, Handle callback); void NonexistentHandlerFrontend(Handle object, Handle last, - Handle name, + Handle name, Label* success, Handle global); @@ -660,15 +660,15 @@ class BaseLoadStubCompiler: public StubCompiler { Handle object, Handle holder, LookupResult* lookup, - Handle name); + Handle name); void GenerateLoadPostInterceptor(Register reg, Handle interceptor_holder, - Handle name, + Handle name, LookupResult* lookup); Handle GetCode(Code::IcFragment fragment, Code::StubType type, - Handle name, + Handle name, InlineCacheState state = MONOMORPHIC); Register receiver() { return registers_[0]; } @@ -681,8 +681,8 @@ class BaseLoadStubCompiler: public StubCompiler { private: virtual Code::Kind kind() = 0; virtual Logger::LogEventsAndTags log_kind(Handle code) = 0; - virtual void JitEvent(Handle name, Handle code) = 0; - virtual void GenerateNameCheck(Handle name, + virtual void JitEvent(Handle name, Handle code) = 0; + virtual void GenerateNameCheck(Handle name, Register name_reg, Label* miss) { } Register* registers_; @@ -696,7 +696,7 @@ class LoadStubCompiler: public BaseLoadStubCompiler { Handle CompileLoadNonexistent(Handle object, Handle last, - Handle name, + Handle name, Handle global); static void GenerateLoadViaGetter(MacroAssembler* masm, @@ -704,13 +704,13 @@ class LoadStubCompiler: public BaseLoadStubCompiler { Handle CompileLoadViaGetter(Handle object, Handle holder, - Handle name, + Handle name, Handle getter); Handle CompileLoadGlobal(Handle object, Handle holder, Handle cell, - Handle name, + Handle name, bool is_dont_delete); static Register receiver() { return registers()[0]; } @@ -722,7 +722,7 @@ class LoadStubCompiler: public BaseLoadStubCompiler { return code->ic_state() == MONOMORPHIC ? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG; } - virtual void JitEvent(Handle name, Handle code); + virtual void JitEvent(Handle name, Handle code); }; @@ -749,8 +749,8 @@ class KeyedLoadStubCompiler: public BaseLoadStubCompiler { return code->ic_state() == MONOMORPHIC ? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG; } - virtual void JitEvent(Handle name, Handle code); - virtual void GenerateNameCheck(Handle name, + virtual void JitEvent(Handle name, Handle code); + virtual void GenerateNameCheck(Handle name, Register name_reg, Label* miss); }; @@ -765,9 +765,9 @@ class StoreStubCompiler: public StubCompiler { Handle CompileStoreField(Handle object, int index, Handle transition, - Handle name); + Handle name); - Handle CompileStoreCallback(Handle name, + Handle CompileStoreCallback(Handle name, Handle object, Handle holder, Handle callback); @@ -775,20 +775,20 @@ class StoreStubCompiler: public StubCompiler { static void GenerateStoreViaSetter(MacroAssembler* masm, Handle setter); - Handle CompileStoreViaSetter(Handle name, + Handle CompileStoreViaSetter(Handle name, Handle object, Handle holder, Handle setter); Handle CompileStoreInterceptor(Handle object, - Handle name); + Handle name); Handle CompileStoreGlobal(Handle object, Handle holder, - Handle name); + Handle name); private: - Handle GetCode(Code::StubType type, Handle name); + Handle GetCode(Code::StubType type, Handle name); StrictModeFlag strict_mode_; }; @@ -806,7 +806,7 @@ class KeyedStoreStubCompiler: public StubCompiler { Handle CompileStoreField(Handle object, int index, Handle transition, - Handle name); + Handle name); Handle CompileStoreElement(Handle receiver_map); @@ -832,7 +832,7 @@ class KeyedStoreStubCompiler: public StubCompiler { private: Handle GetCode(Code::StubType type, - Handle name, + Handle name, InlineCacheState state = MONOMORPHIC); StrictModeFlag strict_mode_; @@ -865,11 +865,11 @@ class CallStubCompiler: public StubCompiler { Handle CompileCallField(Handle object, Handle holder, PropertyIndex index, - Handle name); + Handle name); void CompileHandlerFrontend(Handle object, Handle holder, - Handle name, + Handle name, CheckType check, Label* success); @@ -877,19 +877,19 @@ class CallStubCompiler: public StubCompiler { Handle CompileCallConstant(Handle object, Handle holder, - Handle name, + Handle name, CheckType check, Handle function); Handle CompileCallInterceptor(Handle object, Handle holder, - Handle name); + Handle name); Handle CompileCallGlobal(Handle object, Handle holder, Handle cell, Handle function, - Handle name); + Handle name); static bool HasCustomCallGenerator(Handle function); @@ -919,16 +919,16 @@ class CallStubCompiler: public StubCompiler { Handle function, Handle name); - Handle GetCode(Code::StubType type, Handle name); + Handle GetCode(Code::StubType type, Handle name); Handle GetCode(Handle function); const ParameterCount& arguments() { return arguments_; } - void GenerateNameCheck(Handle name, Label* miss); + void GenerateNameCheck(Handle name, Label* miss); void GenerateGlobalReceiverCheck(Handle object, Handle holder, - Handle name, + Handle name, Label* miss); // Generates code to load the function from the cell checking that diff --git a/src/transitions-inl.h b/src/transitions-inl.h index cfaa99d..45b6457 100644 --- a/src/transitions-inl.h +++ b/src/transitions-inl.h @@ -143,19 +143,19 @@ Object** TransitionArray::GetKeySlot(int transition_number) { } -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); @@ -190,9 +190,9 @@ PropertyDetails TransitionArray::GetTargetDetails(int transition_number) { } -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; } @@ -201,7 +201,7 @@ int TransitionArray::Search(String* name) { void TransitionArray::NoIncrementalWriteBarrierSet(int transition_number, - String* key, + Name* key, Map* target) { FixedArray::NoIncrementalWriteBarrierSet( this, ToKeyIndex(transition_number), key); diff --git a/src/transitions.cc b/src/transitions.cc index 56b6caf..adbe6a1 100644 --- a/src/transitions.cc +++ b/src/transitions.cc @@ -65,13 +65,13 @@ void TransitionArray::NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin, } -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; @@ -107,7 +107,7 @@ MaybeObject* TransitionArray::ExtendToFullTransitionArray() { } -MaybeObject* TransitionArray::CopyInsert(String* name, Map* target) { +MaybeObject* TransitionArray::CopyInsert(Name* name, Map* target) { TransitionArray* result; int number_of_transitions = this->number_of_transitions(); diff --git a/src/transitions.h b/src/transitions.h index 0a66026..7abef47 100644 --- a/src/transitions.h +++ b/src/transitions.h @@ -59,12 +59,12 @@ namespace internal { 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); } @@ -105,7 +105,7 @@ class TransitionArray: public FixedArray { // 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); @@ -114,7 +114,7 @@ class TransitionArray: public FixedArray { // 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, @@ -122,7 +122,7 @@ class TransitionArray: public FixedArray { 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); @@ -195,7 +195,7 @@ class TransitionArray: public FixedArray { } inline void NoIncrementalWriteBarrierSet(int transition_number, - String* key, + Name* key, Map* target); DISALLOW_IMPLICIT_CONSTRUCTORS(TransitionArray); diff --git a/src/v8globals.h b/src/v8globals.h index 072c365..8874cfb 100644 --- a/src/v8globals.h +++ b/src/v8globals.h @@ -128,12 +128,13 @@ class FunctionTemplateInfo; class MemoryChunk; class SeededNumberDictionary; class UnseededNumberDictionary; -class StringDictionary; +class NameDictionary; template class Handle; class Heap; class HeapObject; class IC; class InterceptorInfo; +class JSReceiver; class JSArray; class JSFunction; class JSObject; @@ -155,6 +156,7 @@ class Smi; template class SplayTree; class String; +class Name; class Struct; class Variable; class RelocInfo; diff --git a/src/v8natives.js b/src/v8natives.js index 356ce88..259856b 100644 --- a/src/v8natives.js +++ b/src/v8natives.js @@ -258,9 +258,9 @@ function ObjectValueOf() { 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)); } @@ -277,7 +277,7 @@ function ObjectIsPrototypeOf(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(); @@ -300,7 +300,7 @@ function ObjectDefineGetter(name, fun) { desc.setGet(fun); desc.setEnumerable(true); desc.setConfigurable(true); - DefineOwnProperty(ToObject(receiver), ToString(name), desc, false); + DefineOwnProperty(ToObject(receiver), ToName(name), desc, false); } @@ -309,7 +309,7 @@ function ObjectLookupGetter(name) { if (receiver == null && !IS_UNDETECTABLE(receiver)) { receiver = %GlobalReceiver(global); } - return %LookupAccessor(ToObject(receiver), ToString(name), GETTER); + return %LookupAccessor(ToObject(receiver), ToName(name), GETTER); } @@ -326,7 +326,7 @@ function ObjectDefineSetter(name, fun) { desc.setSet(fun); desc.setEnumerable(true); desc.setConfigurable(true); - DefineOwnProperty(ToObject(receiver), ToString(name), desc, false); + DefineOwnProperty(ToObject(receiver), ToName(name), desc, false); } @@ -335,7 +335,7 @@ function ObjectLookupSetter(name) { if (receiver == null && !IS_UNDETECTABLE(receiver)) { receiver = %GlobalReceiver(global); } - return %LookupAccessor(ToObject(receiver), ToString(name), SETTER); + return %LookupAccessor(ToObject(receiver), ToName(name), SETTER); } @@ -346,7 +346,8 @@ function ObjectKeys(obj) { 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); } @@ -644,7 +645,7 @@ function CallTrap2(handler, name, defaultTrap, x, y) { // 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); @@ -660,7 +661,7 @@ function GetOwnProperty(obj, v) { // 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; @@ -702,7 +703,7 @@ function DefineProxyProperty(obj, p, attributes, should_throw) { // 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; @@ -982,7 +983,7 @@ function ObjectGetOwnPropertyDescriptor(obj, p) { // 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]); } @@ -990,7 +991,7 @@ function ToStringArray(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]); } @@ -1010,7 +1011,7 @@ function ObjectGetOwnPropertyNames(obj) { 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. @@ -1045,13 +1046,13 @@ function ObjectGetOwnPropertyNames(obj) { } } - // 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. @@ -1085,7 +1086,7 @@ function ObjectDefineProperty(obj, p, attributes) { 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 diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index 6aa8903..83fc246 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -6210,12 +6210,13 @@ void ICCompareStub::GenerateMiss(MacroAssembler* masm) { } -void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, - Label* miss, - Label* done, - Register properties, - Handle name, - Register r0) { +void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, + Label* miss, + Label* done, + Register properties, + Handle 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 @@ -6229,10 +6230,10 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, __ 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; @@ -6246,27 +6247,27 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, __ j(equal, done); // Stop if found the property. - __ Cmp(entity_name, Handle(name)); + __ Cmp(entity_name, Handle(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(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(name)); __ push(Immediate(name->Hash())); __ CallStub(&stub); @@ -6276,38 +6277,38 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, } -// 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. @@ -6316,13 +6317,10 @@ void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, __ 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); @@ -6332,7 +6330,7 @@ void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, } -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: @@ -6340,7 +6338,7 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { // 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_. @@ -6364,12 +6362,12 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { // 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. @@ -6386,15 +6384,20 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { __ 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(SYMBOL_TYPE))); + __ j(not_equal, &maybe_in_dictionary); + __ bind(&cont); } } diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h index 675e95b..5dd4064 100644 --- a/src/x64/code-stubs-x64.h +++ b/src/x64/code-stubs-x64.h @@ -316,14 +316,14 @@ class NumberToStringStub: public PlatformCodeStub { }; -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); @@ -332,7 +332,7 @@ class StringDictionaryLookupStub: public PlatformCodeStub { Label* miss, Label* done, Register properties, - Handle name, + Handle name, Register r0); static void GeneratePositiveLookup(MacroAssembler* masm, @@ -350,14 +350,14 @@ class StringDictionaryLookupStub: public PlatformCodeStub { 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()) | diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc index 15423e4..d42a2e9 100644 --- a/src/x64/ic-x64.cc +++ b/src/x64/ic-x64.cc @@ -60,11 +60,11 @@ static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, // 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. @@ -127,21 +127,21 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, 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), @@ -184,21 +184,21 @@ static void GenerateDictionaryStore(MacroAssembler* masm, 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 | @@ -313,31 +313,37 @@ static void GenerateFastArrayLoad(MacroAssembler* masm, } -// 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); } @@ -348,11 +354,11 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { // -- 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. @@ -397,8 +403,8 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { __ 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); @@ -499,7 +505,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); __ ret(0); - __ bind(&index_string); + __ bind(&index_name); __ IndexFromHash(rbx, rax); __ jmp(&index_smi); } @@ -900,7 +906,7 @@ void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) { // 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. @@ -1020,11 +1026,11 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { __ 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 @@ -1072,10 +1078,10 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { __ 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. @@ -1102,14 +1108,14 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { __ 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); @@ -1127,10 +1133,10 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { // 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); @@ -1339,7 +1345,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { // ----------------------------------- Label miss; - GenerateStringDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss); + GenerateNameDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss); // rdx: elements // Search the dictionary placing the result in rax. @@ -1466,7 +1472,7 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) { 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(); diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 5f467e3..24777e8 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -3017,6 +3017,19 @@ void MacroAssembler::AssertString(Register object) { } +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) { @@ -3041,6 +3054,16 @@ Condition MacroAssembler::IsObjectStringType(Register heap_object, } +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(LAST_NAME_TYPE))); + return below_equal; +} + + void MacroAssembler::TryGetFunctionPrototype(Register function, Register result, Label* miss, diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h index 6753724..7827feb 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h @@ -922,6 +922,15 @@ class MacroAssembler: public Assembler { 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). @@ -965,6 +974,9 @@ class MacroAssembler: public Assembler { // 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, diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc index c471569..0d914c3 100644 --- a/src/x64/stub-cache-x64.cc +++ b/src/x64/stub-cache-x64.cc @@ -110,14 +110,14 @@ static void ProbeTable(Isolate* isolate, // 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 name, + Handle 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); @@ -146,12 +146,12 @@ static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, __ 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); } @@ -193,7 +193,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm, __ 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)); @@ -205,7 +205,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm, 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)); @@ -533,7 +533,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { void Compile(MacroAssembler* masm, Handle object, Handle holder, - Handle name, + Handle name, LookupResult* lookup, Register receiver, Register scratch1, @@ -565,7 +565,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { Register scratch3, Handle interceptor_holder, LookupResult* lookup, - Handle name, + Handle name, const CallOptimization& optimization, Label* miss_label) { ASSERT(optimization.is_constant_call()); @@ -658,7 +658,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { Register scratch1, Register scratch2, Register scratch3, - Handle name, + Handle name, Handle interceptor_holder, Label* miss_label) { Register holder = @@ -746,7 +746,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, Handle object, int index, Handle transition, - Handle name, + Handle name, Register receiver_reg, Register name_reg, Register scratch1, @@ -874,7 +874,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, // property. static void GenerateCheckPropertyCell(MacroAssembler* masm, Handle global, - Handle name, + Handle name, Register scratch, Label* miss) { Handle cell = @@ -892,7 +892,7 @@ static void GenerateCheckPropertyCell(MacroAssembler* masm, static void GenerateCheckPropertyCells(MacroAssembler* masm, Handle object, Handle holder, - Handle name, + Handle name, Register scratch, Label* miss) { Handle current = object; @@ -923,7 +923,7 @@ Register StubCompiler::CheckPrototypes(Handle object, Register holder_reg, Register scratch1, Register scratch2, - Handle name, + Handle name, int save_at_depth, Label* miss, PrototypeCheckType check) { @@ -957,11 +957,12 @@ Register StubCompiler::CheckPrototypes(Handle object, if (!current->HasFastProperties() && !current->IsJSGlobalObject() && !current->IsJSGlobalProxy()) { - if (!name->IsInternalizedString()) { - name = factory()->InternalizeString(name); + if (!name->IsUniqueName()) { + ASSERT(name->IsString()); + name = factory()->InternalizeString(Handle::cast(name)); } ASSERT(current->property_dictionary()->FindEntry(*name) == - StringDictionary::kNotFound); + NameDictionary::kNotFound); GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, scratch2); @@ -1047,7 +1048,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( Handle object, Register object_reg, Handle holder, - Handle name, + Handle name, Label* success, Handle callback) { Label miss; @@ -1065,21 +1066,21 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( // 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, @@ -1097,7 +1098,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( void BaseLoadStubCompiler::NonexistentHandlerFrontend( Handle object, Handle last, - Handle name, + Handle name, Label* success, Handle global) { Label miss; @@ -1200,7 +1201,7 @@ void BaseLoadStubCompiler::GenerateLoadInterceptor( Handle object, Handle interceptor_holder, LookupResult* lookup, - Handle name) { + Handle name) { ASSERT(interceptor_holder->HasNamedInterceptor()); ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); @@ -1288,7 +1289,7 @@ void BaseLoadStubCompiler::GenerateLoadInterceptor( } -void CallStubCompiler::GenerateNameCheck(Handle name, Label* miss) { +void CallStubCompiler::GenerateNameCheck(Handle name, Label* miss) { if (kind_ == Code::KEYED_CALL_IC) { __ Cmp(rcx, name); __ j(not_equal, miss); @@ -1298,7 +1299,7 @@ void CallStubCompiler::GenerateNameCheck(Handle name, Label* miss) { void CallStubCompiler::GenerateGlobalReceiverCheck(Handle object, Handle holder, - Handle name, + Handle name, Label* miss) { ASSERT(holder->IsGlobalObject()); @@ -1356,7 +1357,7 @@ void CallStubCompiler::GenerateMissBranch() { Handle CallStubCompiler::CompileCallField(Handle object, Handle holder, PropertyIndex index, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // rcx : function name // rsp[0] : return address @@ -2145,7 +2146,7 @@ Handle CallStubCompiler::CompileFastApiCall( void CallStubCompiler::CompileHandlerFrontend(Handle object, Handle holder, - Handle name, + Handle name, CheckType check, Label* success) { // ----------- S t a t e ------------- @@ -2261,13 +2262,13 @@ void CallStubCompiler::CompileHandlerBackend(Handle function) { Handle CallStubCompiler::CompileCallConstant( Handle object, Handle holder, - Handle name, + Handle name, CheckType check, Handle function) { if (HasCustomCallGenerator(function)) { Handle code = CompileCustomCall(object, holder, Handle::null(), - function, name); + function, Handle::cast(name)); // A null handle means bail out to the regular compiler code below. if (!code.is_null()) return code; } @@ -2285,7 +2286,7 @@ Handle CallStubCompiler::CompileCallConstant( Handle CallStubCompiler::CompileCallInterceptor(Handle object, Handle holder, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // rcx : function name // rsp[0] : return address @@ -2348,7 +2349,7 @@ Handle CallStubCompiler::CompileCallGlobal( Handle holder, Handle cell, Handle function, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // rcx : function name // rsp[0] : return address @@ -2360,7 +2361,8 @@ Handle CallStubCompiler::CompileCallGlobal( // ----------------------------------- if (HasCustomCallGenerator(function)) { - Handle code = CompileCustomCall(object, holder, cell, function, name); + Handle code = CompileCustomCall( + object, holder, cell, function, Handle::cast(name)); // A null handle means bail out to the regular compiler code below. if (!code.is_null()) return code; } @@ -2409,7 +2411,7 @@ Handle CallStubCompiler::CompileCallGlobal( Handle StoreStubCompiler::CompileStoreField(Handle object, int index, Handle transition, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- rax : value // -- rcx : name @@ -2440,7 +2442,7 @@ Handle StoreStubCompiler::CompileStoreField(Handle object, Handle StoreStubCompiler::CompileStoreCallback( - Handle name, + Handle name, Handle receiver, Handle holder, Handle callback) { @@ -2527,7 +2529,7 @@ void StoreStubCompiler::GenerateStoreViaSetter( Handle StoreStubCompiler::CompileStoreViaSetter( - Handle name, + Handle name, Handle receiver, Handle holder, Handle setter) { @@ -2556,7 +2558,7 @@ Handle StoreStubCompiler::CompileStoreViaSetter( Handle StoreStubCompiler::CompileStoreInterceptor( Handle receiver, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- rax : value // -- rcx : name @@ -2603,7 +2605,7 @@ Handle StoreStubCompiler::CompileStoreInterceptor( Handle StoreStubCompiler::CompileStoreGlobal( Handle object, Handle cell, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- rax : value // -- rcx : name @@ -2651,7 +2653,7 @@ Handle StoreStubCompiler::CompileStoreGlobal( Handle KeyedStoreStubCompiler::CompileStoreField(Handle object, int index, Handle transition, - Handle name) { + Handle name) { // ----------- S t a t e ------------- // -- rax : value // -- rcx : key @@ -2756,7 +2758,7 @@ Handle KeyedStoreStubCompiler::CompileStorePolymorphic( Handle LoadStubCompiler::CompileLoadNonexistent( Handle object, Handle last, - Handle name, + Handle name, Handle global) { Label success; @@ -2787,7 +2789,7 @@ Register* KeyedLoadStubCompiler::registers() { } -void KeyedLoadStubCompiler::GenerateNameCheck(Handle name, +void KeyedLoadStubCompiler::GenerateNameCheck(Handle name, Register name_reg, Label* miss) { __ Cmp(name_reg, name); @@ -2836,7 +2838,7 @@ Handle LoadStubCompiler::CompileLoadGlobal( Handle object, Handle global, Handle cell, - Handle name, + Handle name, bool is_dont_delete) { Label success, miss; // TODO(verwaest): Directly store to rax. Currently we cannot do this, since @@ -2903,7 +2905,7 @@ Handle KeyedLoadStubCompiler::CompileLoadElement( Handle BaseLoadStubCompiler::CompilePolymorphicIC( MapHandleList* receiver_maps, CodeHandleList* handlers, - Handle name, + Handle name, Code::StubType type, IcCheckType check) { Label miss; diff --git a/test/mjsunit/harmony/symbols.js b/test/mjsunit/harmony/symbols.js index baec514..b35d950 100644 --- a/test/mjsunit/harmony/symbols.js +++ b/test/mjsunit/harmony/symbols.js @@ -115,7 +115,7 @@ TestSet() function TestMap() { - var map = new Map; + var map = new Map for (var i in symbols) { map.set(symbols[i], i) } @@ -125,3 +125,100 @@ function TestMap() { } } 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) +}