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())); |
Toon Verwaest
2015/02/24 12:24:55
DCHECK(!value->IsMap() || Map::cast(value)->GetCon
Jakob Kummerow
2015/02/24 16:30:25
Done.
| |
5500 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset); | 5498 set_constructor_or_backpointer(value, mode); |
5501 if (object->IsTransitionArray()) { | |
5502 TransitionArray::cast(object)->set_back_pointer_storage(value); | |
5503 } else { | |
5504 WRITE_FIELD(this, kTransitionsOrBackPointerOffset, value); | |
5505 CONDITIONAL_WRITE_BARRIER( | |
5506 GetHeap(), this, kTransitionsOrBackPointerOffset, value, mode); | |
5507 } | |
5508 } | 5499 } |
5509 | 5500 |
5510 | 5501 |
5511 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset) | 5502 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset) |
5512 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset) | 5503 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset) |
5513 ACCESSORS(Map, constructor, Object, kConstructorOffset) | 5504 ACCESSORS(Map, constructor_or_backpointer, Object, |
5505 kConstructorOrBackPointerOffset) | |
5506 | |
5507 Object* Map::GetConstructor() const { | |
5508 Object* maybe_constructor = constructor_or_backpointer(); | |
5509 // Follow any back pointers. | |
5510 while (maybe_constructor->IsMap()) { | |
5511 maybe_constructor = | |
5512 Map::cast(maybe_constructor)->constructor_or_backpointer(); | |
5513 } | |
5514 return maybe_constructor; | |
5515 } | |
5516 void Map::SetConstructor(Object* constructor, WriteBarrierMode mode) { | |
5517 // Never overwrite a back pointer with a constructor. | |
5518 DCHECK(!constructor_or_backpointer()->IsMap()); | |
5519 set_constructor_or_backpointer(constructor, mode); | |
5520 } | |
5514 | 5521 |
5515 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) | 5522 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) |
5516 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset) | 5523 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset) |
5517 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset) | 5524 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset) |
5518 | 5525 |
5519 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset) | 5526 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset) |
5520 ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset) | 5527 ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset) |
5521 ACCESSORS(GlobalObject, global_proxy, JSObject, kGlobalProxyOffset) | 5528 ACCESSORS(GlobalObject, global_proxy, JSObject, kGlobalProxyOffset) |
5522 | 5529 |
5523 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset) | 5530 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 | 6199 // When there is no initial map and the prototype is a JSObject, the |
6193 // initial map field is used for the prototype field. | 6200 // initial map field is used for the prototype field. |
6194 return prototype_or_initial_map(); | 6201 return prototype_or_initial_map(); |
6195 } | 6202 } |
6196 | 6203 |
6197 | 6204 |
6198 Object* JSFunction::prototype() { | 6205 Object* JSFunction::prototype() { |
6199 DCHECK(has_prototype()); | 6206 DCHECK(has_prototype()); |
6200 // If the function's prototype property has been set to a non-JSObject | 6207 // 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. | 6208 // value, that value is stored in the constructor field of the map. |
6202 if (map()->has_non_instance_prototype()) return map()->constructor(); | 6209 if (map()->has_non_instance_prototype()) { |
6210 Object* prototype = map()->constructor_or_backpointer(); | |
6211 // The map must have a prototype in that field, not a back pointer. | |
6212 DCHECK(!prototype->IsMap()); | |
6213 return prototype; | |
6214 } | |
6203 return instance_prototype(); | 6215 return instance_prototype(); |
6204 } | 6216 } |
6205 | 6217 |
6206 | 6218 |
6207 bool JSFunction::should_have_prototype() { | 6219 bool JSFunction::should_have_prototype() { |
6208 return map()->function_with_prototype(); | 6220 return map()->function_with_prototype(); |
6209 } | 6221 } |
6210 | 6222 |
6211 | 6223 |
6212 bool JSFunction::is_compiled() { | 6224 bool JSFunction::is_compiled() { |
(...skipping 1402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7615 #undef READ_SHORT_FIELD | 7627 #undef READ_SHORT_FIELD |
7616 #undef WRITE_SHORT_FIELD | 7628 #undef WRITE_SHORT_FIELD |
7617 #undef READ_BYTE_FIELD | 7629 #undef READ_BYTE_FIELD |
7618 #undef WRITE_BYTE_FIELD | 7630 #undef WRITE_BYTE_FIELD |
7619 #undef NOBARRIER_READ_BYTE_FIELD | 7631 #undef NOBARRIER_READ_BYTE_FIELD |
7620 #undef NOBARRIER_WRITE_BYTE_FIELD | 7632 #undef NOBARRIER_WRITE_BYTE_FIELD |
7621 | 7633 |
7622 } } // namespace v8::internal | 7634 } } // namespace v8::internal |
7623 | 7635 |
7624 #endif // V8_OBJECTS_INL_H_ | 7636 #endif // V8_OBJECTS_INL_H_ |
OLD | NEW |