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 |