OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 // Review notes: | 5 // Review notes: |
6 // | 6 // |
7 // - The use of macros in these inline functions may seem superfluous | 7 // - The use of macros in these inline functions may seem superfluous |
8 // but it is absolutely needed to make sure gcc generates optimal | 8 // but it is absolutely needed to make sure gcc generates optimal |
9 // code. gcc is not happy when attempting to inline too deep. | 9 // code. gcc is not happy when attempting to inline too deep. |
10 // | 10 // |
(...skipping 5342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5353 // This function does not support appending double field descriptors and | 5353 // This function does not support appending double field descriptors and |
5354 // it should never try to (otherwise, layout descriptor must be updated too). | 5354 // it should never try to (otherwise, layout descriptor must be updated too). |
5355 #ifdef DEBUG | 5355 #ifdef DEBUG |
5356 PropertyDetails details = desc->GetDetails(); | 5356 PropertyDetails details = desc->GetDetails(); |
5357 CHECK(details.type() != DATA || !details.representation().IsDouble()); | 5357 CHECK(details.type() != DATA || !details.representation().IsDouble()); |
5358 #endif | 5358 #endif |
5359 } | 5359 } |
5360 | 5360 |
5361 | 5361 |
5362 Object* Map::GetBackPointer() { | 5362 Object* Map::GetBackPointer() { |
5363 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset); | 5363 Object* object = constructor_or_backpointer(); |
5364 if (object->IsTransitionArray()) { | 5364 if (object->IsMap()) { |
5365 return TransitionArray::cast(object)->back_pointer_storage(); | |
5366 } else { | |
5367 DCHECK(object->IsMap() || object->IsUndefined()); | |
5368 return object; | 5365 return object; |
5369 } | 5366 } |
| 5367 return GetIsolate()->heap()->undefined_value(); |
5370 } | 5368 } |
5371 | 5369 |
5372 | 5370 |
5373 bool Map::HasElementsTransition() { | 5371 bool Map::HasElementsTransition() { |
5374 return HasTransitionArray() && transitions()->HasElementsTransition(); | 5372 return HasTransitionArray() && transitions()->HasElementsTransition(); |
5375 } | 5373 } |
5376 | 5374 |
5377 | 5375 |
5378 bool Map::HasTransitionArray() const { | 5376 bool Map::HasTransitionArray() const { |
5379 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset); | 5377 Object* object = READ_FIELD(this, kTransitionsOffset); |
5380 return object->IsTransitionArray(); | 5378 return object->IsTransitionArray(); |
5381 } | 5379 } |
5382 | 5380 |
5383 | 5381 |
5384 Map* Map::elements_transition_map() { | 5382 Map* Map::elements_transition_map() { |
5385 int index = | 5383 int index = |
5386 transitions()->SearchSpecial(GetHeap()->elements_transition_symbol()); | 5384 transitions()->SearchSpecial(GetHeap()->elements_transition_symbol()); |
5387 return transitions()->GetTarget(index); | 5385 return transitions()->GetTarget(index); |
5388 } | 5386 } |
5389 | 5387 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5439 } | 5437 } |
5440 | 5438 |
5441 | 5439 |
5442 bool Map::HasPrototypeTransitions() { | 5440 bool Map::HasPrototypeTransitions() { |
5443 return HasTransitionArray() && transitions()->HasPrototypeTransitions(); | 5441 return HasTransitionArray() && transitions()->HasPrototypeTransitions(); |
5444 } | 5442 } |
5445 | 5443 |
5446 | 5444 |
5447 TransitionArray* Map::transitions() const { | 5445 TransitionArray* Map::transitions() const { |
5448 DCHECK(HasTransitionArray()); | 5446 DCHECK(HasTransitionArray()); |
5449 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset); | 5447 Object* object = READ_FIELD(this, kTransitionsOffset); |
5450 return TransitionArray::cast(object); | 5448 return TransitionArray::cast(object); |
5451 } | 5449 } |
5452 | 5450 |
5453 | 5451 |
5454 void Map::set_transitions(TransitionArray* transition_array, | 5452 void Map::set_transitions(TransitionArray* transition_array, |
5455 WriteBarrierMode mode) { | 5453 WriteBarrierMode mode) { |
5456 // Transition arrays are not shared. When one is replaced, it should not | 5454 // Transition arrays are not shared. When one is replaced, it should not |
5457 // keep referenced objects alive, so we zap it. | 5455 // keep referenced objects alive, so we zap it. |
5458 // When there is another reference to the array somewhere (e.g. a handle), | 5456 // When there is another reference to the array somewhere (e.g. a handle), |
5459 // not zapping turns from a waste of memory into a source of crashes. | 5457 // not zapping turns from a waste of memory into a source of crashes. |
(...skipping 14 matching lines...) Expand all Loading... |
5474 } | 5472 } |
5475 DCHECK_NE(TransitionArray::kNotFound, new_target_index); | 5473 DCHECK_NE(TransitionArray::kNotFound, new_target_index); |
5476 DCHECK_EQ(target, transition_array->GetTarget(new_target_index)); | 5474 DCHECK_EQ(target, transition_array->GetTarget(new_target_index)); |
5477 } | 5475 } |
5478 } | 5476 } |
5479 #endif | 5477 #endif |
5480 DCHECK(transitions() != transition_array); | 5478 DCHECK(transitions() != transition_array); |
5481 ZapTransitions(); | 5479 ZapTransitions(); |
5482 } | 5480 } |
5483 | 5481 |
5484 WRITE_FIELD(this, kTransitionsOrBackPointerOffset, transition_array); | 5482 WRITE_FIELD(this, kTransitionsOffset, transition_array); |
5485 CONDITIONAL_WRITE_BARRIER( | 5483 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTransitionsOffset, |
5486 GetHeap(), this, kTransitionsOrBackPointerOffset, transition_array, mode); | 5484 transition_array, mode); |
5487 } | 5485 } |
5488 | 5486 |
5489 | 5487 |
5490 void Map::init_back_pointer(Object* undefined) { | 5488 void Map::init_transitions(Object* undefined) { |
5491 DCHECK(undefined->IsUndefined()); | 5489 DCHECK(undefined->IsUndefined()); |
5492 WRITE_FIELD(this, kTransitionsOrBackPointerOffset, undefined); | 5490 WRITE_FIELD(this, kTransitionsOffset, undefined); |
5493 } | 5491 } |
5494 | 5492 |
5495 | 5493 |
5496 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { | 5494 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { |
5497 DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE); | 5495 DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE); |
5498 DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) || | 5496 DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) || |
5499 (value->IsMap() && GetBackPointer()->IsUndefined())); | 5497 (value->IsMap() && GetBackPointer()->IsUndefined())); |
5500 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset); | 5498 DCHECK(!value->IsMap() || |
5501 if (object->IsTransitionArray()) { | 5499 Map::cast(value)->GetConstructor() == constructor_or_backpointer()); |
5502 TransitionArray::cast(object)->set_back_pointer_storage(value); | 5500 set_constructor_or_backpointer(value, mode); |
5503 } else { | |
5504 WRITE_FIELD(this, kTransitionsOrBackPointerOffset, value); | |
5505 CONDITIONAL_WRITE_BARRIER( | |
5506 GetHeap(), this, kTransitionsOrBackPointerOffset, value, mode); | |
5507 } | |
5508 } | 5501 } |
5509 | 5502 |
5510 | 5503 |
5511 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset) | 5504 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset) |
5512 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset) | 5505 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset) |
5513 ACCESSORS(Map, constructor, Object, kConstructorOffset) | 5506 ACCESSORS(Map, constructor_or_backpointer, Object, |
| 5507 kConstructorOrBackPointerOffset) |
| 5508 |
| 5509 Object* Map::GetConstructor() const { |
| 5510 Object* maybe_constructor = constructor_or_backpointer(); |
| 5511 // Follow any back pointers. |
| 5512 while (maybe_constructor->IsMap()) { |
| 5513 maybe_constructor = |
| 5514 Map::cast(maybe_constructor)->constructor_or_backpointer(); |
| 5515 } |
| 5516 return maybe_constructor; |
| 5517 } |
| 5518 void Map::SetConstructor(Object* constructor, WriteBarrierMode mode) { |
| 5519 // Never overwrite a back pointer with a constructor. |
| 5520 DCHECK(!constructor_or_backpointer()->IsMap()); |
| 5521 set_constructor_or_backpointer(constructor, mode); |
| 5522 } |
5514 | 5523 |
5515 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) | 5524 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) |
5516 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset) | 5525 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset) |
5517 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset) | 5526 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset) |
5518 | 5527 |
5519 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset) | 5528 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset) |
5520 ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset) | 5529 ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset) |
5521 ACCESSORS(GlobalObject, global_proxy, JSObject, kGlobalProxyOffset) | 5530 ACCESSORS(GlobalObject, global_proxy, JSObject, kGlobalProxyOffset) |
5522 | 5531 |
5523 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset) | 5532 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset) |
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6192 // When there is no initial map and the prototype is a JSObject, the | 6201 // When there is no initial map and the prototype is a JSObject, the |
6193 // initial map field is used for the prototype field. | 6202 // initial map field is used for the prototype field. |
6194 return prototype_or_initial_map(); | 6203 return prototype_or_initial_map(); |
6195 } | 6204 } |
6196 | 6205 |
6197 | 6206 |
6198 Object* JSFunction::prototype() { | 6207 Object* JSFunction::prototype() { |
6199 DCHECK(has_prototype()); | 6208 DCHECK(has_prototype()); |
6200 // If the function's prototype property has been set to a non-JSObject | 6209 // If the function's prototype property has been set to a non-JSObject |
6201 // value, that value is stored in the constructor field of the map. | 6210 // value, that value is stored in the constructor field of the map. |
6202 if (map()->has_non_instance_prototype()) return map()->constructor(); | 6211 if (map()->has_non_instance_prototype()) { |
| 6212 Object* prototype = map()->GetConstructor(); |
| 6213 // The map must have a prototype in that field, not a back pointer. |
| 6214 DCHECK(!prototype->IsMap()); |
| 6215 return prototype; |
| 6216 } |
6203 return instance_prototype(); | 6217 return instance_prototype(); |
6204 } | 6218 } |
6205 | 6219 |
6206 | 6220 |
6207 bool JSFunction::should_have_prototype() { | 6221 bool JSFunction::should_have_prototype() { |
6208 return map()->function_with_prototype(); | 6222 return map()->function_with_prototype(); |
6209 } | 6223 } |
6210 | 6224 |
6211 | 6225 |
6212 bool JSFunction::is_compiled() { | 6226 bool JSFunction::is_compiled() { |
(...skipping 1402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7615 #undef READ_SHORT_FIELD | 7629 #undef READ_SHORT_FIELD |
7616 #undef WRITE_SHORT_FIELD | 7630 #undef WRITE_SHORT_FIELD |
7617 #undef READ_BYTE_FIELD | 7631 #undef READ_BYTE_FIELD |
7618 #undef WRITE_BYTE_FIELD | 7632 #undef WRITE_BYTE_FIELD |
7619 #undef NOBARRIER_READ_BYTE_FIELD | 7633 #undef NOBARRIER_READ_BYTE_FIELD |
7620 #undef NOBARRIER_WRITE_BYTE_FIELD | 7634 #undef NOBARRIER_WRITE_BYTE_FIELD |
7621 | 7635 |
7622 } } // namespace v8::internal | 7636 } } // namespace v8::internal |
7623 | 7637 |
7624 #endif // V8_OBJECTS_INL_H_ | 7638 #endif // V8_OBJECTS_INL_H_ |
OLD | NEW |