| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_PROPERTY_H_ | 5 #ifndef V8_PROPERTY_H_ |
| 6 #define V8_PROPERTY_H_ | 6 #define V8_PROPERTY_H_ |
| 7 | 7 |
| 8 #include "isolate.h" | 8 #include "isolate.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 void DescriptorResult(JSObject* holder, PropertyDetails details, int number) { | 173 void DescriptorResult(JSObject* holder, PropertyDetails details, int number) { |
| 174 lookup_type_ = DESCRIPTOR_TYPE; | 174 lookup_type_ = DESCRIPTOR_TYPE; |
| 175 holder_ = holder; | 175 holder_ = holder; |
| 176 transition_ = NULL; | 176 transition_ = NULL; |
| 177 details_ = details; | 177 details_ = details; |
| 178 number_ = number; | 178 number_ = number; |
| 179 } | 179 } |
| 180 | 180 |
| 181 bool CanHoldValue(Handle<Object> value) { | 181 bool CanHoldValue(Handle<Object> value) { |
| 182 if (IsNormal()) return true; | 182 if (IsNormal()) return true; |
| 183 ASSERT(!IsTransition()); | |
| 184 return value->FitsRepresentation(details_.representation()); | 183 return value->FitsRepresentation(details_.representation()); |
| 185 } | 184 } |
| 186 | 185 |
| 187 void TransitionResult(JSObject* holder, Map* target) { | 186 void TransitionResult(JSObject* holder, Map* target) { |
| 188 lookup_type_ = TRANSITION_TYPE; | 187 lookup_type_ = TRANSITION_TYPE; |
| 189 details_ = PropertyDetails(NONE, TRANSITION, Representation::None()); | 188 details_ = target->GetLastDescriptorDetails(); |
| 190 holder_ = holder; | 189 holder_ = holder; |
| 191 transition_ = target; | 190 transition_ = target; |
| 192 number_ = 0xAAAA; | 191 number_ = 0xAAAA; |
| 193 } | 192 } |
| 194 | 193 |
| 195 void DictionaryResult(JSObject* holder, int entry) { | 194 void DictionaryResult(JSObject* holder, int entry) { |
| 196 lookup_type_ = DICTIONARY_TYPE; | 195 lookup_type_ = DICTIONARY_TYPE; |
| 197 holder_ = holder; | 196 holder_ = holder; |
| 198 transition_ = NULL; | 197 transition_ = NULL; |
| 199 details_ = holder->property_dictionary()->DetailsAt(entry); | 198 details_ = holder->property_dictionary()->DetailsAt(entry); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 return JSProxy::cast(holder_); | 231 return JSProxy::cast(holder_); |
| 233 } | 232 } |
| 234 | 233 |
| 235 PropertyType type() const { | 234 PropertyType type() const { |
| 236 ASSERT(IsFound()); | 235 ASSERT(IsFound()); |
| 237 return details_.type(); | 236 return details_.type(); |
| 238 } | 237 } |
| 239 | 238 |
| 240 Representation representation() const { | 239 Representation representation() const { |
| 241 ASSERT(IsFound()); | 240 ASSERT(IsFound()); |
| 242 ASSERT(!IsTransition()); | |
| 243 ASSERT(details_.type() != NONEXISTENT); | 241 ASSERT(details_.type() != NONEXISTENT); |
| 244 return details_.representation(); | 242 return details_.representation(); |
| 245 } | 243 } |
| 246 | 244 |
| 247 PropertyAttributes GetAttributes() const { | 245 PropertyAttributes GetAttributes() const { |
| 248 ASSERT(!IsTransition()); | |
| 249 ASSERT(IsFound()); | 246 ASSERT(IsFound()); |
| 250 ASSERT(details_.type() != NONEXISTENT); | 247 ASSERT(details_.type() != NONEXISTENT); |
| 251 return details_.attributes(); | 248 return details_.attributes(); |
| 252 } | 249 } |
| 253 | 250 |
| 254 PropertyDetails GetPropertyDetails() const { | 251 PropertyDetails GetPropertyDetails() const { |
| 255 ASSERT(!IsTransition()); | |
| 256 return details_; | 252 return details_; |
| 257 } | 253 } |
| 258 | 254 |
| 259 bool IsFastPropertyType() const { | 255 bool IsFastPropertyType() const { |
| 260 ASSERT(IsFound()); | 256 ASSERT(IsFound()); |
| 261 return IsTransition() || type() != NORMAL; | 257 return IsTransition() || type() != NORMAL; |
| 262 } | 258 } |
| 263 | 259 |
| 264 // Property callbacks does not include transitions to callbacks. | 260 // Property callbacks does not include transitions to callbacks. |
| 265 bool IsPropertyCallbacks() const { | 261 bool IsPropertyCallbacks() const { |
| 266 ASSERT(!(details_.type() == CALLBACKS && !IsFound())); | 262 ASSERT(!(details_.type() == CALLBACKS && !IsFound())); |
| 267 return details_.type() == CALLBACKS; | 263 return !IsTransition() && details_.type() == CALLBACKS; |
| 268 } | 264 } |
| 269 | 265 |
| 270 bool IsReadOnly() const { | 266 bool IsReadOnly() const { |
| 271 ASSERT(IsFound()); | 267 ASSERT(IsFound()); |
| 272 ASSERT(!IsTransition()); | |
| 273 ASSERT(details_.type() != NONEXISTENT); | 268 ASSERT(details_.type() != NONEXISTENT); |
| 274 return details_.IsReadOnly(); | 269 return details_.IsReadOnly(); |
| 275 } | 270 } |
| 276 | 271 |
| 277 bool IsField() const { | 272 bool IsField() const { |
| 278 ASSERT(!(details_.type() == FIELD && !IsFound())); | 273 ASSERT(!(details_.type() == FIELD && !IsFound())); |
| 279 return details_.type() == FIELD; | 274 return IsDescriptorOrDictionary() && type() == FIELD; |
| 280 } | 275 } |
| 281 | 276 |
| 282 bool IsNormal() const { | 277 bool IsNormal() const { |
| 283 ASSERT(!(details_.type() == NORMAL && !IsFound())); | 278 ASSERT(!(details_.type() == NORMAL && !IsFound())); |
| 284 return details_.type() == NORMAL; | 279 return IsDescriptorOrDictionary() && type() == NORMAL; |
| 285 } | 280 } |
| 286 | 281 |
| 287 bool IsConstant() const { | 282 bool IsConstant() const { |
| 288 ASSERT(!(details_.type() == CONSTANT && !IsFound())); | 283 ASSERT(!(details_.type() == CONSTANT && !IsFound())); |
| 289 return details_.type() == CONSTANT; | 284 return IsDescriptorOrDictionary() && type() == CONSTANT; |
| 290 } | 285 } |
| 291 | 286 |
| 292 bool IsConstantFunction() const { | 287 bool IsConstantFunction() const { |
| 293 return IsConstant() && GetValue()->IsJSFunction(); | 288 return IsConstant() && GetConstant()->IsJSFunction(); |
| 294 } | 289 } |
| 295 | 290 |
| 296 bool IsDontDelete() const { return details_.IsDontDelete(); } | 291 bool IsDontDelete() const { return details_.IsDontDelete(); } |
| 297 bool IsDontEnum() const { return details_.IsDontEnum(); } | 292 bool IsDontEnum() const { return details_.IsDontEnum(); } |
| 298 bool IsFound() const { return lookup_type_ != NOT_FOUND; } | 293 bool IsFound() const { return lookup_type_ != NOT_FOUND; } |
| 294 bool IsDescriptorOrDictionary() const { |
| 295 return lookup_type_ == DESCRIPTOR_TYPE || lookup_type_ == DICTIONARY_TYPE; |
| 296 } |
| 299 bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; } | 297 bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; } |
| 300 bool IsHandler() const { return lookup_type_ == HANDLER_TYPE; } | 298 bool IsHandler() const { return lookup_type_ == HANDLER_TYPE; } |
| 301 bool IsInterceptor() const { return lookup_type_ == INTERCEPTOR_TYPE; } | 299 bool IsInterceptor() const { return lookup_type_ == INTERCEPTOR_TYPE; } |
| 302 | 300 |
| 303 // Is the result is a property excluding transitions and the null descriptor? | 301 // Is the result is a property excluding transitions and the null descriptor? |
| 304 bool IsProperty() const { | 302 bool IsProperty() const { |
| 305 return IsFound() && !IsTransition(); | 303 return IsFound() && !IsTransition(); |
| 306 } | 304 } |
| 307 | 305 |
| 308 bool IsDataProperty() const { | 306 bool IsDataProperty() const { |
| 309 switch (type()) { | 307 switch (lookup_type_) { |
| 310 case FIELD: | 308 case NOT_FOUND: |
| 311 case NORMAL: | 309 case TRANSITION_TYPE: |
| 312 case CONSTANT: | 310 case HANDLER_TYPE: |
| 313 return true; | 311 case INTERCEPTOR_TYPE: |
| 314 case CALLBACKS: { | |
| 315 Object* callback = GetCallbackObject(); | |
| 316 return callback->IsAccessorInfo() || callback->IsForeign(); | |
| 317 } | |
| 318 case HANDLER: | |
| 319 case INTERCEPTOR: | |
| 320 case TRANSITION: | |
| 321 case NONEXISTENT: | |
| 322 return false; | 312 return false; |
| 313 |
| 314 case DESCRIPTOR_TYPE: |
| 315 case DICTIONARY_TYPE: |
| 316 switch (type()) { |
| 317 case FIELD: |
| 318 case NORMAL: |
| 319 case CONSTANT: |
| 320 return true; |
| 321 case CALLBACKS: { |
| 322 Object* callback = GetCallbackObject(); |
| 323 return callback->IsAccessorInfo() || callback->IsForeign(); |
| 324 } |
| 325 case HANDLER: |
| 326 case INTERCEPTOR: |
| 327 case NONEXISTENT: |
| 328 UNREACHABLE(); |
| 329 return false; |
| 330 } |
| 323 } | 331 } |
| 324 UNREACHABLE(); | 332 UNREACHABLE(); |
| 325 return false; | 333 return false; |
| 326 } | 334 } |
| 327 | 335 |
| 328 bool IsCacheable() const { return cacheable_; } | 336 bool IsCacheable() const { return cacheable_; } |
| 329 void DisallowCaching() { cacheable_ = false; } | 337 void DisallowCaching() { cacheable_ = false; } |
| 330 | 338 |
| 331 Object* GetLazyValue() const { | 339 Object* GetLazyValue() const { |
| 332 switch (type()) { | 340 switch (lookup_type_) { |
| 333 case FIELD: | 341 case NOT_FOUND: |
| 334 return holder()->RawFastPropertyAt(GetFieldIndex().field_index()); | 342 case TRANSITION_TYPE: |
| 335 case NORMAL: { | 343 case HANDLER_TYPE: |
| 336 Object* value; | 344 case INTERCEPTOR_TYPE: |
| 337 value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry()); | 345 return isolate()->heap()->the_hole_value(); |
| 338 if (holder()->IsGlobalObject()) { | 346 |
| 339 value = PropertyCell::cast(value)->value(); | 347 case DESCRIPTOR_TYPE: |
| 348 case DICTIONARY_TYPE: |
| 349 switch (type()) { |
| 350 case FIELD: |
| 351 return holder()->RawFastPropertyAt(GetFieldIndex().field_index()); |
| 352 case NORMAL: { |
| 353 Object* value = holder()->property_dictionary()->ValueAt( |
| 354 GetDictionaryEntry()); |
| 355 if (holder()->IsGlobalObject()) { |
| 356 value = PropertyCell::cast(value)->value(); |
| 357 } |
| 358 return value; |
| 359 } |
| 360 case CONSTANT: |
| 361 return GetConstant(); |
| 362 case CALLBACKS: |
| 363 return isolate()->heap()->the_hole_value(); |
| 364 case HANDLER: |
| 365 case INTERCEPTOR: |
| 366 case NONEXISTENT: |
| 367 UNREACHABLE(); |
| 368 return NULL; |
| 340 } | 369 } |
| 341 return value; | |
| 342 } | |
| 343 case CONSTANT: | |
| 344 return GetConstant(); | |
| 345 case CALLBACKS: | |
| 346 case HANDLER: | |
| 347 case INTERCEPTOR: | |
| 348 case TRANSITION: | |
| 349 case NONEXISTENT: | |
| 350 return isolate()->heap()->the_hole_value(); | |
| 351 } | 370 } |
| 352 UNREACHABLE(); | 371 UNREACHABLE(); |
| 353 return NULL; | 372 return NULL; |
| 354 } | 373 } |
| 355 | 374 |
| 356 Map* GetTransitionTarget() const { | 375 Map* GetTransitionTarget() const { |
| 376 ASSERT(IsTransition()); |
| 357 return transition_; | 377 return transition_; |
| 358 } | 378 } |
| 359 | 379 |
| 360 PropertyDetails GetTransitionDetails() const { | |
| 361 ASSERT(IsTransition()); | |
| 362 return transition_->GetLastDescriptorDetails(); | |
| 363 } | |
| 364 | |
| 365 bool IsTransitionToField() const { | 380 bool IsTransitionToField() const { |
| 366 return IsTransition() && GetTransitionDetails().type() == FIELD; | 381 return IsTransition() && details_.type() == FIELD; |
| 367 } | 382 } |
| 368 | 383 |
| 369 bool IsTransitionToConstant() const { | 384 bool IsTransitionToConstant() const { |
| 370 return IsTransition() && GetTransitionDetails().type() == CONSTANT; | 385 return IsTransition() && details_.type() == CONSTANT; |
| 371 } | 386 } |
| 372 | 387 |
| 373 int GetDescriptorIndex() const { | 388 int GetDescriptorIndex() const { |
| 374 ASSERT(lookup_type_ == DESCRIPTOR_TYPE); | 389 ASSERT(lookup_type_ == DESCRIPTOR_TYPE); |
| 375 return number_; | 390 return number_; |
| 376 } | 391 } |
| 377 | 392 |
| 378 PropertyIndex GetFieldIndex() const { | 393 PropertyIndex GetFieldIndex() const { |
| 379 ASSERT(lookup_type_ == DESCRIPTOR_TYPE); | 394 ASSERT(lookup_type_ == DESCRIPTOR_TYPE); |
| 380 return PropertyIndex::NewFieldIndex(GetFieldIndexFromMap(holder()->map())); | 395 return PropertyIndex::NewFieldIndex(GetFieldIndexFromMap(holder()->map())); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 402 JSFunction* GetConstantFunctionFromMap(Map* map) const { | 417 JSFunction* GetConstantFunctionFromMap(Map* map) const { |
| 403 return JSFunction::cast(GetConstantFromMap(map)); | 418 return JSFunction::cast(GetConstantFromMap(map)); |
| 404 } | 419 } |
| 405 | 420 |
| 406 Object* GetConstant() const { | 421 Object* GetConstant() const { |
| 407 ASSERT(type() == CONSTANT); | 422 ASSERT(type() == CONSTANT); |
| 408 return GetValue(); | 423 return GetValue(); |
| 409 } | 424 } |
| 410 | 425 |
| 411 Object* GetCallbackObject() const { | 426 Object* GetCallbackObject() const { |
| 412 ASSERT(type() == CALLBACKS && !IsTransition()); | 427 ASSERT(!IsTransition()); |
| 428 ASSERT(type() == CALLBACKS); |
| 413 return GetValue(); | 429 return GetValue(); |
| 414 } | 430 } |
| 415 | 431 |
| 416 #ifdef OBJECT_PRINT | 432 #ifdef OBJECT_PRINT |
| 417 void Print(FILE* out); | 433 void Print(FILE* out); |
| 418 #endif | 434 #endif |
| 419 | 435 |
| 420 Object* GetValue() const { | 436 Object* GetValue() const { |
| 421 if (lookup_type_ == DESCRIPTOR_TYPE) { | 437 if (lookup_type_ == DESCRIPTOR_TYPE) { |
| 422 return GetValueFromMap(holder()->map()); | 438 return GetValueFromMap(holder()->map()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 JSReceiver* holder_; | 473 JSReceiver* holder_; |
| 458 Map* transition_; | 474 Map* transition_; |
| 459 int number_; | 475 int number_; |
| 460 bool cacheable_; | 476 bool cacheable_; |
| 461 PropertyDetails details_; | 477 PropertyDetails details_; |
| 462 }; | 478 }; |
| 463 | 479 |
| 464 } } // namespace v8::internal | 480 } } // namespace v8::internal |
| 465 | 481 |
| 466 #endif // V8_PROPERTY_H_ | 482 #endif // V8_PROPERTY_H_ |
| OLD | NEW |