diff options
Diffstat (limited to 'chromium/v8/src/property.h')
-rw-r--r-- | chromium/v8/src/property.h | 407 |
1 files changed, 201 insertions, 206 deletions
diff --git a/chromium/v8/src/property.h b/chromium/v8/src/property.h index da772dc86c3..ebb43430a04 100644 --- a/chromium/v8/src/property.h +++ b/chromium/v8/src/property.h @@ -1,60 +1,35 @@ -// Copyright 2012 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #ifndef V8_PROPERTY_H_ #define V8_PROPERTY_H_ -#include "allocation.h" -#include "transitions.h" +#include "src/isolate.h" +#include "src/factory.h" +#include "src/field-index.h" +#include "src/field-index-inl.h" +#include "src/types.h" namespace v8 { namespace internal { - // Abstraction for elements in instance-descriptor arrays. // // Each descriptor has a key, property attributes, property type, // property index (in the actual instance-descriptor array) and // optionally a piece of data. -// - class Descriptor BASE_EMBEDDED { public: - MUST_USE_RESULT MaybeObject* KeyToUniqueName() { + void KeyToUniqueName() { if (!key_->IsUniqueName()) { - MaybeObject* maybe_result = - key_->GetIsolate()->heap()->InternalizeString(String::cast(key_)); - if (!maybe_result->To(&key_)) return maybe_result; + key_ = key_->GetIsolate()->factory()->InternalizeString( + Handle<String>::cast(key_)); } - return key_; } - Name* GetKey() { return key_; } - Object* GetValue() { return value_; } + Handle<Name> GetKey() { return key_; } + Handle<Object> GetValue() { return value_; } PropertyDetails GetDetails() { return details_; } #ifdef OBJECT_PRINT @@ -64,26 +39,26 @@ class Descriptor BASE_EMBEDDED { void SetSortedKeyIndex(int index) { details_ = details_.set_pointer(index); } private: - Name* key_; - Object* value_; + Handle<Name> key_; + Handle<Object> value_; PropertyDetails details_; protected: Descriptor() : details_(Smi::FromInt(0)) {} - void Init(Name* key, Object* value, PropertyDetails details) { + void Init(Handle<Name> key, Handle<Object> value, PropertyDetails details) { key_ = key; value_ = value; details_ = details; } - Descriptor(Name* key, Object* value, PropertyDetails details) + Descriptor(Handle<Name> key, Handle<Object> value, PropertyDetails details) : key_(key), value_(value), details_(details) { } - Descriptor(Name* key, - Object* value, + Descriptor(Handle<Name> key, + Handle<Object> value, PropertyAttributes attributes, PropertyType type, Representation representation, @@ -93,91 +68,49 @@ class Descriptor BASE_EMBEDDED { details_(attributes, type, representation, field_index) { } friend class DescriptorArray; + friend class Map; }; -class FieldDescriptor: public Descriptor { +class FieldDescriptor V8_FINAL : public Descriptor { public: - FieldDescriptor(Name* key, + FieldDescriptor(Handle<Name> key, int field_index, PropertyAttributes attributes, Representation representation) - : Descriptor(key, Smi::FromInt(0), attributes, + : Descriptor(key, HeapType::Any(key->GetIsolate()), attributes, FIELD, representation, field_index) {} + FieldDescriptor(Handle<Name> key, + int field_index, + Handle<HeapType> field_type, + PropertyAttributes attributes, + Representation representation) + : Descriptor(key, field_type, attributes, FIELD, + representation, field_index) { } }; -class ConstantDescriptor: public Descriptor { +class ConstantDescriptor V8_FINAL : public Descriptor { public: - ConstantDescriptor(Name* key, - Object* value, + ConstantDescriptor(Handle<Name> key, + Handle<Object> value, PropertyAttributes attributes) : Descriptor(key, value, attributes, CONSTANT, value->OptimalRepresentation()) {} }; -class CallbacksDescriptor: public Descriptor { +class CallbacksDescriptor V8_FINAL : public Descriptor { public: - CallbacksDescriptor(Name* key, - Object* foreign, + CallbacksDescriptor(Handle<Name> key, + Handle<Object> foreign, PropertyAttributes attributes) : Descriptor(key, foreign, attributes, CALLBACKS, Representation::Tagged()) {} }; -// Holds a property index value distinguishing if it is a field index or an -// index inside the object header. -class PropertyIndex { - public: - static PropertyIndex NewFieldIndex(int index) { - return PropertyIndex(index, false); - } - static PropertyIndex NewHeaderIndex(int index) { - return PropertyIndex(index, true); - } - - bool is_field_index() { return (index_ & kHeaderIndexBit) == 0; } - bool is_header_index() { return (index_ & kHeaderIndexBit) != 0; } - - int field_index() { - ASSERT(is_field_index()); - return value(); - } - int header_index() { - ASSERT(is_header_index()); - return value(); - } - - bool is_inobject(Handle<JSObject> holder) { - if (is_header_index()) return true; - return field_index() < holder->map()->inobject_properties(); - } - - int translate(Handle<JSObject> holder) { - if (is_header_index()) return header_index(); - int index = field_index() - holder->map()->inobject_properties(); - if (index >= 0) return index; - return index + holder->map()->instance_size() / kPointerSize; - } - - private: - static const int kHeaderIndexBit = 1 << 31; - static const int kIndexMask = ~kHeaderIndexBit; - - int value() { return index_ & kIndexMask; } - - PropertyIndex(int index, bool is_header_based) - : index_(index | (is_header_based ? kHeaderIndexBit : 0)) { - ASSERT(index <= kIndexMask); - } - - int index_; -}; - - -class LookupResult BASE_EMBEDDED { +class LookupResult V8_FINAL BASE_EMBEDDED { public: explicit LookupResult(Isolate* isolate) : isolate_(isolate), @@ -187,12 +120,12 @@ class LookupResult BASE_EMBEDDED { transition_(NULL), cacheable_(true), details_(NONE, NONEXISTENT, Representation::None()) { - isolate->SetTopLookupResult(this); + isolate->set_top_lookup_result(this); } ~LookupResult() { ASSERT(isolate()->top_lookup_result() == this); - isolate()->SetTopLookupResult(next_); + isolate()->set_top_lookup_result(next_); } Isolate* isolate() const { return isolate_; } @@ -200,23 +133,39 @@ class LookupResult BASE_EMBEDDED { void DescriptorResult(JSObject* holder, PropertyDetails details, int number) { lookup_type_ = DESCRIPTOR_TYPE; holder_ = holder; + transition_ = NULL; details_ = details; number_ = number; - transition_ = NULL; } - bool CanHoldValue(Handle<Object> value) { - if (IsNormal()) return true; - ASSERT(!IsTransition()); - return value->FitsRepresentation(details_.representation()); + bool CanHoldValue(Handle<Object> value) const { + switch (type()) { + case NORMAL: + return true; + case FIELD: + return value->FitsRepresentation(representation()) && + GetFieldType()->NowContains(value); + case CONSTANT: + ASSERT(GetConstant() != *value || + value->FitsRepresentation(representation())); + return GetConstant() == *value; + case CALLBACKS: + case HANDLER: + case INTERCEPTOR: + return true; + case NONEXISTENT: + UNREACHABLE(); + } + UNREACHABLE(); + return true; } void TransitionResult(JSObject* holder, Map* target) { lookup_type_ = TRANSITION_TYPE; - details_ = PropertyDetails(NONE, TRANSITION, Representation::None()); + number_ = target->LastAdded(); + details_ = target->instance_descriptors()->GetDetails(number_); holder_ = holder; transition_ = target; - number_ = 0xAAAA; } void DictionaryResult(JSObject* holder, int entry) { @@ -246,200 +195,216 @@ class LookupResult BASE_EMBEDDED { lookup_type_ = NOT_FOUND; details_ = PropertyDetails(NONE, NONEXISTENT, Representation::None()); holder_ = NULL; + transition_ = NULL; } - JSObject* holder() { + JSObject* holder() const { ASSERT(IsFound()); return JSObject::cast(holder_); } - JSProxy* proxy() { + JSProxy* proxy() const { ASSERT(IsHandler()); return JSProxy::cast(holder_); } - PropertyType type() { + PropertyType type() const { ASSERT(IsFound()); return details_.type(); } - Representation representation() { + Representation representation() const { ASSERT(IsFound()); - ASSERT(!IsTransition()); ASSERT(details_.type() != NONEXISTENT); return details_.representation(); } - PropertyAttributes GetAttributes() { - ASSERT(!IsTransition()); + PropertyAttributes GetAttributes() const { ASSERT(IsFound()); ASSERT(details_.type() != NONEXISTENT); return details_.attributes(); } - PropertyDetails GetPropertyDetails() { - ASSERT(!IsTransition()); + PropertyDetails GetPropertyDetails() const { return details_; } - bool IsFastPropertyType() { + bool IsFastPropertyType() const { ASSERT(IsFound()); return IsTransition() || type() != NORMAL; } // Property callbacks does not include transitions to callbacks. - bool IsPropertyCallbacks() { + bool IsPropertyCallbacks() const { ASSERT(!(details_.type() == CALLBACKS && !IsFound())); - return details_.type() == CALLBACKS; + return !IsTransition() && details_.type() == CALLBACKS; } - bool IsReadOnly() { + bool IsReadOnly() const { ASSERT(IsFound()); - ASSERT(!IsTransition()); ASSERT(details_.type() != NONEXISTENT); return details_.IsReadOnly(); } - bool IsField() { + bool IsField() const { ASSERT(!(details_.type() == FIELD && !IsFound())); - return details_.type() == FIELD; + return IsDescriptorOrDictionary() && type() == FIELD; } - bool IsNormal() { + bool IsNormal() const { ASSERT(!(details_.type() == NORMAL && !IsFound())); - return details_.type() == NORMAL; + return IsDescriptorOrDictionary() && type() == NORMAL; } - bool IsConstant() { + bool IsConstant() const { ASSERT(!(details_.type() == CONSTANT && !IsFound())); - return details_.type() == CONSTANT; + return IsDescriptorOrDictionary() && type() == CONSTANT; } - bool IsConstantFunction() { - return IsConstant() && GetValue()->IsJSFunction(); + bool IsConstantFunction() const { + return IsConstant() && GetConstant()->IsJSFunction(); } - bool IsDontDelete() { return details_.IsDontDelete(); } - bool IsDontEnum() { return details_.IsDontEnum(); } - bool IsFound() { return lookup_type_ != NOT_FOUND; } - bool IsTransition() { return lookup_type_ == TRANSITION_TYPE; } - bool IsHandler() { return lookup_type_ == HANDLER_TYPE; } - bool IsInterceptor() { return lookup_type_ == INTERCEPTOR_TYPE; } + bool IsDontDelete() const { return details_.IsDontDelete(); } + bool IsDontEnum() const { return details_.IsDontEnum(); } + bool IsFound() const { return lookup_type_ != NOT_FOUND; } + bool IsDescriptorOrDictionary() const { + return lookup_type_ == DESCRIPTOR_TYPE || lookup_type_ == DICTIONARY_TYPE; + } + bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; } + bool IsHandler() const { return lookup_type_ == HANDLER_TYPE; } + bool IsInterceptor() const { return lookup_type_ == INTERCEPTOR_TYPE; } // Is the result is a property excluding transitions and the null descriptor? - bool IsProperty() { + bool IsProperty() const { return IsFound() && !IsTransition(); } - bool IsDataProperty() { - switch (type()) { - case FIELD: - case NORMAL: - case CONSTANT: - return true; - case CALLBACKS: { - Object* callback = GetCallbackObject(); - return callback->IsAccessorInfo() || callback->IsForeign(); - } - case HANDLER: - case INTERCEPTOR: - case TRANSITION: - case NONEXISTENT: + bool IsDataProperty() const { + switch (lookup_type_) { + case NOT_FOUND: + case TRANSITION_TYPE: + case HANDLER_TYPE: + case INTERCEPTOR_TYPE: return false; + + case DESCRIPTOR_TYPE: + case DICTIONARY_TYPE: + switch (type()) { + case FIELD: + case NORMAL: + case CONSTANT: + return true; + case CALLBACKS: { + Object* callback = GetCallbackObject(); + ASSERT(!callback->IsForeign()); + return callback->IsAccessorInfo(); + } + case HANDLER: + case INTERCEPTOR: + case NONEXISTENT: + UNREACHABLE(); + return false; + } } UNREACHABLE(); return false; } - bool IsCacheable() { return cacheable_; } + bool IsCacheable() const { return cacheable_; } void DisallowCaching() { cacheable_ = false; } - Object* GetLazyValue() { - switch (type()) { - case FIELD: - return holder()->RawFastPropertyAt(GetFieldIndex().field_index()); - case NORMAL: { - Object* value; - value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry()); - if (holder()->IsGlobalObject()) { - value = PropertyCell::cast(value)->value(); - } - return value; - } - case CONSTANT: - return GetConstant(); - case CALLBACKS: - case HANDLER: - case INTERCEPTOR: - case TRANSITION: - case NONEXISTENT: + Object* GetLazyValue() const { + switch (lookup_type_) { + case NOT_FOUND: + case TRANSITION_TYPE: + case HANDLER_TYPE: + case INTERCEPTOR_TYPE: return isolate()->heap()->the_hole_value(); + + case DESCRIPTOR_TYPE: + case DICTIONARY_TYPE: + switch (type()) { + case FIELD: + return holder()->RawFastPropertyAt(GetFieldIndex()); + case NORMAL: { + Object* value = holder()->property_dictionary()->ValueAt( + GetDictionaryEntry()); + if (holder()->IsGlobalObject()) { + value = PropertyCell::cast(value)->value(); + } + return value; + } + case CONSTANT: + return GetConstant(); + case CALLBACKS: + return isolate()->heap()->the_hole_value(); + case HANDLER: + case INTERCEPTOR: + case NONEXISTENT: + UNREACHABLE(); + return NULL; + } } UNREACHABLE(); return NULL; } - Map* GetTransitionTarget() { + Map* GetTransitionTarget() const { + ASSERT(IsTransition()); return transition_; } - PropertyDetails GetTransitionDetails() { - return transition_->GetLastDescriptorDetails(); + bool IsTransitionToField() const { + return IsTransition() && details_.type() == FIELD; } - bool IsTransitionToField() { - return IsTransition() && GetTransitionDetails().type() == FIELD; + bool IsTransitionToConstant() const { + return IsTransition() && details_.type() == CONSTANT; } - bool IsTransitionToConstant() { - return IsTransition() && GetTransitionDetails().type() == CONSTANT; - } - - int GetTransitionIndex() { - ASSERT(IsTransition()); - return number_; - } - - int GetDescriptorIndex() { + int GetDescriptorIndex() const { ASSERT(lookup_type_ == DESCRIPTOR_TYPE); return number_; } - PropertyIndex GetFieldIndex() { - ASSERT(lookup_type_ == DESCRIPTOR_TYPE); - return PropertyIndex::NewFieldIndex(GetFieldIndexFromMap(holder()->map())); + FieldIndex GetFieldIndex() const { + ASSERT(lookup_type_ == DESCRIPTOR_TYPE || + lookup_type_ == TRANSITION_TYPE); + return FieldIndex::ForLookupResult(this); } - int GetLocalFieldIndexFromMap(Map* map) { + int GetLocalFieldIndexFromMap(Map* map) const { return GetFieldIndexFromMap(map) - map->inobject_properties(); } - int GetDictionaryEntry() { + int GetDictionaryEntry() const { ASSERT(lookup_type_ == DICTIONARY_TYPE); return number_; } - JSFunction* GetConstantFunction() { + JSFunction* GetConstantFunction() const { ASSERT(type() == CONSTANT); return JSFunction::cast(GetValue()); } - Object* GetConstantFromMap(Map* map) { + Object* GetConstantFromMap(Map* map) const { ASSERT(type() == CONSTANT); return GetValueFromMap(map); } - JSFunction* GetConstantFunctionFromMap(Map* map) { + JSFunction* GetConstantFunctionFromMap(Map* map) const { return JSFunction::cast(GetConstantFromMap(map)); } - Object* GetConstant() { + Object* GetConstant() const { ASSERT(type() == CONSTANT); return GetValue(); } - Object* GetCallbackObject() { - ASSERT(type() == CALLBACKS && !IsTransition()); + Object* GetCallbackObject() const { + ASSERT(!IsTransition()); + ASSERT(type() == CALLBACKS); return GetValue(); } @@ -447,9 +412,11 @@ class LookupResult BASE_EMBEDDED { void Print(FILE* out); #endif - Object* GetValue() { + Object* GetValue() const { if (lookup_type_ == DESCRIPTOR_TYPE) { return GetValueFromMap(holder()->map()); + } else if (lookup_type_ == TRANSITION_TYPE) { + return GetValueFromMap(transition_); } // In the dictionary case, the data is held in the value field. ASSERT(lookup_type_ == DICTIONARY_TYPE); @@ -457,17 +424,46 @@ class LookupResult BASE_EMBEDDED { } Object* GetValueFromMap(Map* map) const { - ASSERT(lookup_type_ == DESCRIPTOR_TYPE); + ASSERT(lookup_type_ == DESCRIPTOR_TYPE || + lookup_type_ == TRANSITION_TYPE); ASSERT(number_ < map->NumberOfOwnDescriptors()); return map->instance_descriptors()->GetValue(number_); } int GetFieldIndexFromMap(Map* map) const { - ASSERT(lookup_type_ == DESCRIPTOR_TYPE); + ASSERT(lookup_type_ == DESCRIPTOR_TYPE || + lookup_type_ == TRANSITION_TYPE); ASSERT(number_ < map->NumberOfOwnDescriptors()); return map->instance_descriptors()->GetFieldIndex(number_); } + HeapType* GetFieldType() const { + ASSERT(type() == FIELD); + if (lookup_type_ == DESCRIPTOR_TYPE) { + return GetFieldTypeFromMap(holder()->map()); + } + ASSERT(lookup_type_ == TRANSITION_TYPE); + return GetFieldTypeFromMap(transition_); + } + + HeapType* GetFieldTypeFromMap(Map* map) const { + ASSERT(lookup_type_ == DESCRIPTOR_TYPE || + lookup_type_ == TRANSITION_TYPE); + ASSERT(number_ < map->NumberOfOwnDescriptors()); + return map->instance_descriptors()->GetFieldType(number_); + } + + Map* GetFieldOwner() const { + return GetFieldOwnerFromMap(holder()->map()); + } + + Map* GetFieldOwnerFromMap(Map* map) const { + ASSERT(lookup_type_ == DESCRIPTOR_TYPE || + lookup_type_ == TRANSITION_TYPE); + ASSERT(number_ < map->NumberOfOwnDescriptors()); + return map->FindFieldOwner(number_); + } + void Iterate(ObjectVisitor* visitor); private: @@ -491,7 +487,6 @@ class LookupResult BASE_EMBEDDED { PropertyDetails details_; }; - } } // namespace v8::internal #endif // V8_PROPERTY_H_ |