00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef V8_PROPERTY_H_
00029 #define V8_PROPERTY_H_
00030
00031 namespace v8 { namespace internal {
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 class Descriptor BASE_EMBEDDED {
00042 public:
00043 static int IndexFromValue(Object* value) {
00044 return Smi::cast(value)->value();
00045 }
00046
00047 Object* KeyToSymbol() {
00048 if (!key_->IsSymbol()) {
00049 Object* result = Heap::LookupSymbol(key_);
00050 if (result->IsFailure()) return result;
00051 key_ = String::cast(result);
00052 }
00053 return key_;
00054 }
00055
00056 String* GetKey() { return key_; }
00057 Object* GetValue() { return value_; }
00058 PropertyDetails GetDetails() { return details_; }
00059
00060 #ifdef DEBUG
00061 void Print();
00062 #endif
00063
00064 void SetEnumerationIndex(int index) {
00065 ASSERT(PropertyDetails::IsValidIndex(index));
00066 details_ = PropertyDetails(details_.attributes(), details_.type(), index);
00067 }
00068
00069 private:
00070 String* key_;
00071 Object* value_;
00072 PropertyDetails details_;
00073
00074 protected:
00075 Descriptor() : details_(Smi::FromInt(0)) {}
00076
00077 void Init(String* key, Object* value, PropertyDetails details) {
00078 key_ = key;
00079 value_ = value;
00080 details_ = details;
00081 }
00082
00083 Descriptor(String* key, Object* value, PropertyDetails details)
00084 : key_(key),
00085 value_(value),
00086 details_(details) { }
00087
00088 Descriptor(String* key,
00089 Object* value,
00090 PropertyAttributes attributes,
00091 PropertyType type,
00092 int index = 0)
00093 : key_(key),
00094 value_(value),
00095 details_(attributes, type, index) { }
00096
00097 friend class DescriptorWriter;
00098 friend class DescriptorReader;
00099 friend class DescriptorArray;
00100 };
00101
00102
00103
00104
00105
00106 class MapTransitionDescriptor: public Descriptor {
00107 public:
00108 MapTransitionDescriptor(String* key, Map* map, PropertyAttributes attributes)
00109 : Descriptor(key, map, attributes, MAP_TRANSITION) { }
00110 };
00111
00112
00113
00114
00115
00116
00117 class ConstTransitionDescriptor: public Descriptor {
00118 public:
00119 explicit ConstTransitionDescriptor(String* key)
00120 : Descriptor(key, Smi::FromInt(0), NONE, CONSTANT_TRANSITION) { }
00121 };
00122
00123
00124 class FieldDescriptor: public Descriptor {
00125 public:
00126 FieldDescriptor(String* key,
00127 int field_index,
00128 PropertyAttributes attributes,
00129 int index = 0)
00130 : Descriptor(key, Smi::FromInt(field_index), attributes, FIELD, index) {}
00131 };
00132
00133
00134 class ConstantFunctionDescriptor: public Descriptor {
00135 public:
00136 ConstantFunctionDescriptor(String* key,
00137 JSFunction* function,
00138 PropertyAttributes attributes,
00139 int index = 0)
00140 : Descriptor(key, function, attributes, CONSTANT_FUNCTION, index) {}
00141 };
00142
00143
00144 class CallbacksDescriptor: public Descriptor {
00145 public:
00146 CallbacksDescriptor(String* key,
00147 Object* proxy,
00148 PropertyAttributes attributes,
00149 int index = 0)
00150 : Descriptor(key, proxy, attributes, CALLBACKS, index) {}
00151 };
00152
00153
00154 class LookupResult BASE_EMBEDDED {
00155 public:
00156
00157 enum {
00158 NOT_FOUND,
00159 DESCRIPTOR_TYPE,
00160 DICTIONARY_TYPE,
00161 INTERCEPTOR_TYPE,
00162 CONSTANT_TYPE
00163 } lookup_type_;
00164
00165 LookupResult()
00166 : lookup_type_(NOT_FOUND),
00167 cacheable_(true),
00168 details_(NONE, NORMAL) {}
00169
00170 void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
00171 lookup_type_ = DESCRIPTOR_TYPE;
00172 holder_ = holder;
00173 details_ = details;
00174 number_ = number;
00175 }
00176
00177 void ConstantResult(JSObject* holder) {
00178 lookup_type_ = CONSTANT_TYPE;
00179 holder_ = holder;
00180 details_ =
00181 PropertyDetails(static_cast<PropertyAttributes>(DONT_ENUM |
00182 DONT_DELETE),
00183 CALLBACKS);
00184 number_ = -1;
00185 }
00186
00187 void DictionaryResult(JSObject* holder, int entry) {
00188 lookup_type_ = DICTIONARY_TYPE;
00189 holder_ = holder;
00190 details_ = holder->property_dictionary()->DetailsAt(entry);
00191 number_ = entry;
00192 }
00193
00194 void InterceptorResult(JSObject* holder) {
00195 lookup_type_ = INTERCEPTOR_TYPE;
00196 holder_ = holder;
00197 details_ = PropertyDetails(NONE, INTERCEPTOR);
00198 }
00199
00200 void NotFound() {
00201 lookup_type_ = NOT_FOUND;
00202 }
00203
00204 JSObject* holder() {
00205 ASSERT(IsValid());
00206 return holder_;
00207 }
00208
00209 PropertyType type() {
00210 ASSERT(IsValid());
00211 return details_.type();
00212 }
00213
00214 bool IsTransitionType() {
00215 PropertyType t = type();
00216 if (t == MAP_TRANSITION || t == CONSTANT_TRANSITION) return true;
00217 return false;
00218 }
00219
00220 PropertyAttributes GetAttributes() {
00221 ASSERT(IsValid());
00222 return details_.attributes();
00223 }
00224
00225 PropertyDetails GetPropertyDetails() {
00226 return details_;
00227 }
00228
00229 bool IsReadOnly() { return details_.IsReadOnly(); }
00230 bool IsDontDelete() { return details_.IsDontDelete(); }
00231 bool IsDontEnum() { return details_.IsDontEnum(); }
00232
00233 bool IsValid() { return lookup_type_ != NOT_FOUND; }
00234 bool IsNotFound() { return lookup_type_ == NOT_FOUND; }
00235
00236
00237
00238 bool IsProperty() {
00239 return IsValid() && type() < FIRST_PHANTOM_PROPERTY_TYPE;
00240 }
00241
00242 bool IsCacheable() { return cacheable_; }
00243 void DisallowCaching() { cacheable_ = false; }
00244
00245
00246 bool IsLoaded() {
00247 if (lookup_type_ == DESCRIPTOR_TYPE || lookup_type_ == DICTIONARY_TYPE) {
00248 Object* value = GetValue();
00249 if (value->IsJSFunction()) {
00250 return JSFunction::cast(value)->IsLoaded();
00251 }
00252 }
00253 return true;
00254 }
00255
00256 Map* GetTransitionMap() {
00257 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
00258 ASSERT(type() == MAP_TRANSITION);
00259 return Map::cast(GetValue());
00260 }
00261
00262 int GetFieldIndex() {
00263 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
00264 ASSERT(type() == FIELD);
00265 return Descriptor::IndexFromValue(GetValue());
00266 }
00267
00268 int GetDictionaryEntry() {
00269 ASSERT(lookup_type_ == DICTIONARY_TYPE);
00270 return number_;
00271 }
00272
00273 JSFunction* GetConstantFunction() {
00274 ASSERT(type() == CONSTANT_FUNCTION);
00275 return JSFunction::cast(GetValue());
00276 }
00277
00278 Object* GetCallbackObject() {
00279 if (lookup_type_ == CONSTANT_TYPE) {
00280
00281 return Heap::prototype_accessors();
00282 }
00283 return GetValue();
00284 }
00285
00286 #ifdef DEBUG
00287 void Print();
00288 #endif
00289
00290 Object* GetValue() {
00291 if (lookup_type_ == DESCRIPTOR_TYPE) {
00292 DescriptorArray* descriptors = holder()->map()->instance_descriptors();
00293 return descriptors->GetValue(number_);
00294 }
00295
00296 ASSERT(lookup_type_ == DICTIONARY_TYPE);
00297 return holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
00298 }
00299
00300 private:
00301 JSObject* holder_;
00302 int number_;
00303 bool cacheable_;
00304 PropertyDetails details_;
00305 };
00306
00307
00308
00309
00310 class DescriptorStream BASE_EMBEDDED {
00311 public:
00312 explicit DescriptorStream(DescriptorArray* descriptors, int pos) {
00313 descriptors_ = descriptors;
00314 pos_ = pos;
00315 limit_ = descriptors_->number_of_descriptors();
00316 }
00317
00318
00319 bool eos() { return pos_ >= limit_; }
00320
00321 int next_position() { return pos_ + 1; }
00322 void advance() { pos_ = next_position(); }
00323
00324 protected:
00325 DescriptorArray* descriptors_;
00326 int pos_;
00327 int limit_;
00328 };
00329
00330
00331 class DescriptorReader: public DescriptorStream {
00332 public:
00333 explicit DescriptorReader(DescriptorArray* descriptors, int pos = 0)
00334 : DescriptorStream(descriptors, pos) {}
00335
00336 String* GetKey() { return descriptors_->GetKey(pos_); }
00337 Object* GetValue() { return descriptors_->GetValue(pos_); }
00338 PropertyDetails GetDetails() {
00339 return PropertyDetails(descriptors_->GetDetails(pos_));
00340 }
00341
00342 int GetFieldIndex() { return Descriptor::IndexFromValue(GetValue()); }
00343
00344 bool IsDontEnum() { return GetDetails().IsDontEnum(); }
00345
00346 PropertyType type() { return GetDetails().type(); }
00347
00348
00349 bool IsTransition() {
00350 PropertyType t = type();
00351 ASSERT(t != INTERCEPTOR);
00352 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
00353 }
00354
00355 bool IsNullDescriptor() {
00356 return type() == NULL_DESCRIPTOR;
00357 }
00358
00359 JSFunction* GetConstantFunction() { return JSFunction::cast(GetValue()); }
00360
00361 AccessorDescriptor* GetCallbacks() {
00362 ASSERT(type() == CALLBACKS);
00363 Proxy* p = Proxy::cast(GetCallbacksObject());
00364 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
00365 }
00366
00367 Object* GetCallbacksObject() {
00368 ASSERT(type() == CALLBACKS);
00369 return GetValue();
00370 }
00371
00372 bool Equals(String* name) { return name->Equals(GetKey()); }
00373
00374 void Get(Descriptor* desc) {
00375 descriptors_->Get(pos_, desc);
00376 }
00377 };
00378
00379 class DescriptorWriter: public DescriptorStream {
00380 public:
00381 explicit DescriptorWriter(DescriptorArray* descriptors)
00382 : DescriptorStream(descriptors, 0) {}
00383
00384
00385 void Write(Descriptor* desc);
00386
00387 void WriteFrom(DescriptorReader* reader);
00388 };
00389
00390 } }
00391
00392 #endif // V8_PROPERTY_H_