1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 // - The use of macros in these inline functions may seem superfluous
31 // but it is absolutely needed to make sure gcc generates optimal
32 // code. gcc is not happy when attempting to inline too deep.
35 #ifndef V8_OBJECTS_INL_H_
36 #define V8_OBJECTS_INL_H_
41 #include "conversions-inl.h"
46 #include "store-buffer.h"
49 #include "incremental-marking.h"
54 PropertyDetails::PropertyDetails(Smi* smi) {
55 value_ = smi->value();
59 Smi* PropertyDetails::AsSmi() {
60 return Smi::FromInt(value_);
64 PropertyDetails PropertyDetails::AsDeleted() {
65 Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
66 return PropertyDetails(smi);
70 #define TYPE_CHECKER(type, instancetype) \
71 bool Object::Is##type() { \
72 return Object::IsHeapObject() && \
73 HeapObject::cast(this)->map()->instance_type() == instancetype; \
77 #define CAST_ACCESSOR(type) \
78 type* type::cast(Object* object) { \
79 ASSERT(object->Is##type()); \
80 return reinterpret_cast<type*>(object); \
84 #define INT_ACCESSORS(holder, name, offset) \
85 int holder::name() { return READ_INT_FIELD(this, offset); } \
86 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
89 #define ACCESSORS(holder, name, type, offset) \
90 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
91 void holder::set_##name(type* value, WriteBarrierMode mode) { \
92 WRITE_FIELD(this, offset, value); \
93 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \
97 #define SMI_ACCESSORS(holder, name, offset) \
98 int holder::name() { \
99 Object* value = READ_FIELD(this, offset); \
100 return Smi::cast(value)->value(); \
102 void holder::set_##name(int value) { \
103 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
107 #define BOOL_GETTER(holder, field, name, offset) \
108 bool holder::name() { \
109 return BooleanBit::get(field(), offset); \
113 #define BOOL_ACCESSORS(holder, field, name, offset) \
114 bool holder::name() { \
115 return BooleanBit::get(field(), offset); \
117 void holder::set_##name(bool value) { \
118 set_##field(BooleanBit::set(field(), offset, value)); \
122 bool Object::IsFixedArrayBase() {
123 return IsFixedArray() || IsFixedDoubleArray();
127 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
128 // There is a constraint on the object; check.
129 if (!this->IsJSObject()) return false;
130 // Fetch the constructor function of the object.
131 Object* cons_obj = JSObject::cast(this)->map()->constructor();
132 if (!cons_obj->IsJSFunction()) return false;
133 JSFunction* fun = JSFunction::cast(cons_obj);
134 // Iterate through the chain of inheriting function templates to
135 // see if the required one occurs.
136 for (Object* type = fun->shared()->function_data();
137 type->IsFunctionTemplateInfo();
138 type = FunctionTemplateInfo::cast(type)->parent_template()) {
139 if (type == expected) return true;
141 // Didn't find the required type in the inheritance chain.
146 bool Object::IsSmi() {
147 return HAS_SMI_TAG(this);
151 bool Object::IsHeapObject() {
152 return Internals::HasHeapObjectTag(this);
156 bool Object::NonFailureIsHeapObject() {
157 ASSERT(!this->IsFailure());
158 return (reinterpret_cast<intptr_t>(this) & kSmiTagMask) != 0;
162 TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
165 bool Object::IsString() {
166 return Object::IsHeapObject()
167 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
171 bool Object::IsSpecObject() {
172 return Object::IsHeapObject()
173 && HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
177 bool Object::IsSpecFunction() {
178 if (!Object::IsHeapObject()) return false;
179 InstanceType type = HeapObject::cast(this)->map()->instance_type();
180 return type == JS_FUNCTION_TYPE || type == JS_FUNCTION_PROXY_TYPE;
184 bool Object::IsSymbol() {
185 if (!this->IsHeapObject()) return false;
186 uint32_t type = HeapObject::cast(this)->map()->instance_type();
187 // Because the symbol tag is non-zero and no non-string types have the
188 // symbol bit set we can test for symbols with a very simple test
190 STATIC_ASSERT(kSymbolTag != 0);
191 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
192 return (type & kIsSymbolMask) != 0;
196 bool Object::IsConsString() {
197 if (!IsString()) return false;
198 return StringShape(String::cast(this)).IsCons();
202 bool Object::IsSlicedString() {
203 if (!IsString()) return false;
204 return StringShape(String::cast(this)).IsSliced();
208 bool Object::IsSeqString() {
209 if (!IsString()) return false;
210 return StringShape(String::cast(this)).IsSequential();
214 bool Object::IsSeqAsciiString() {
215 if (!IsString()) return false;
216 return StringShape(String::cast(this)).IsSequential() &&
217 String::cast(this)->IsAsciiRepresentation();
221 bool Object::IsSeqTwoByteString() {
222 if (!IsString()) return false;
223 return StringShape(String::cast(this)).IsSequential() &&
224 String::cast(this)->IsTwoByteRepresentation();
228 bool Object::IsExternalString() {
229 if (!IsString()) return false;
230 return StringShape(String::cast(this)).IsExternal();
234 bool Object::IsExternalAsciiString() {
235 if (!IsString()) return false;
236 return StringShape(String::cast(this)).IsExternal() &&
237 String::cast(this)->IsAsciiRepresentation();
241 bool Object::IsExternalTwoByteString() {
242 if (!IsString()) return false;
243 return StringShape(String::cast(this)).IsExternal() &&
244 String::cast(this)->IsTwoByteRepresentation();
247 bool Object::HasValidElements() {
248 // Dictionary is covered under FixedArray.
249 return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray();
252 StringShape::StringShape(String* str)
253 : type_(str->map()->instance_type()) {
255 ASSERT((type_ & kIsNotStringMask) == kStringTag);
259 StringShape::StringShape(Map* map)
260 : type_(map->instance_type()) {
262 ASSERT((type_ & kIsNotStringMask) == kStringTag);
266 StringShape::StringShape(InstanceType t)
267 : type_(static_cast<uint32_t>(t)) {
269 ASSERT((type_ & kIsNotStringMask) == kStringTag);
273 bool StringShape::IsSymbol() {
275 STATIC_ASSERT(kSymbolTag != 0);
276 return (type_ & kIsSymbolMask) != 0;
280 bool String::IsAsciiRepresentation() {
281 uint32_t type = map()->instance_type();
282 return (type & kStringEncodingMask) == kAsciiStringTag;
286 bool String::IsTwoByteRepresentation() {
287 uint32_t type = map()->instance_type();
288 return (type & kStringEncodingMask) == kTwoByteStringTag;
292 bool String::IsAsciiRepresentationUnderneath() {
293 uint32_t type = map()->instance_type();
294 STATIC_ASSERT(kIsIndirectStringTag != 0);
295 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
297 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
298 case kAsciiStringTag:
300 case kTwoByteStringTag:
302 default: // Cons or sliced string. Need to go deeper.
303 return GetUnderlying()->IsAsciiRepresentation();
308 bool String::IsTwoByteRepresentationUnderneath() {
309 uint32_t type = map()->instance_type();
310 STATIC_ASSERT(kIsIndirectStringTag != 0);
311 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
313 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
314 case kAsciiStringTag:
316 case kTwoByteStringTag:
318 default: // Cons or sliced string. Need to go deeper.
319 return GetUnderlying()->IsTwoByteRepresentation();
324 bool String::HasOnlyAsciiChars() {
325 uint32_t type = map()->instance_type();
326 return (type & kStringEncodingMask) == kAsciiStringTag ||
327 (type & kAsciiDataHintMask) == kAsciiDataHintTag;
331 bool StringShape::IsCons() {
332 return (type_ & kStringRepresentationMask) == kConsStringTag;
336 bool StringShape::IsSliced() {
337 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
341 bool StringShape::IsIndirect() {
342 return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
346 bool StringShape::IsExternal() {
347 return (type_ & kStringRepresentationMask) == kExternalStringTag;
351 bool StringShape::IsSequential() {
352 return (type_ & kStringRepresentationMask) == kSeqStringTag;
356 StringRepresentationTag StringShape::representation_tag() {
357 uint32_t tag = (type_ & kStringRepresentationMask);
358 return static_cast<StringRepresentationTag>(tag);
362 uint32_t StringShape::encoding_tag() {
363 return type_ & kStringEncodingMask;
367 uint32_t StringShape::full_representation_tag() {
368 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
372 STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
373 Internals::kFullStringRepresentationMask);
376 bool StringShape::IsSequentialAscii() {
377 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
381 bool StringShape::IsSequentialTwoByte() {
382 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
386 bool StringShape::IsExternalAscii() {
387 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
391 bool StringShape::IsExternalTwoByte() {
392 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
396 STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
397 Internals::kExternalTwoByteRepresentationTag);
400 uc32 FlatStringReader::Get(int index) {
401 ASSERT(0 <= index && index <= length_);
403 return static_cast<const byte*>(start_)[index];
405 return static_cast<const uc16*>(start_)[index];
410 bool Object::IsNumber() {
411 return IsSmi() || IsHeapNumber();
415 TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
416 TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
419 bool Object::IsFiller() {
420 if (!Object::IsHeapObject()) return false;
421 InstanceType instance_type = HeapObject::cast(this)->map()->instance_type();
422 return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
426 TYPE_CHECKER(ExternalPixelArray, EXTERNAL_PIXEL_ARRAY_TYPE)
429 bool Object::IsExternalArray() {
430 if (!Object::IsHeapObject())
432 InstanceType instance_type =
433 HeapObject::cast(this)->map()->instance_type();
434 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
435 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
439 TYPE_CHECKER(ExternalByteArray, EXTERNAL_BYTE_ARRAY_TYPE)
440 TYPE_CHECKER(ExternalUnsignedByteArray, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
441 TYPE_CHECKER(ExternalShortArray, EXTERNAL_SHORT_ARRAY_TYPE)
442 TYPE_CHECKER(ExternalUnsignedShortArray, EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
443 TYPE_CHECKER(ExternalIntArray, EXTERNAL_INT_ARRAY_TYPE)
444 TYPE_CHECKER(ExternalUnsignedIntArray, EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
445 TYPE_CHECKER(ExternalFloatArray, EXTERNAL_FLOAT_ARRAY_TYPE)
446 TYPE_CHECKER(ExternalDoubleArray, EXTERNAL_DOUBLE_ARRAY_TYPE)
449 bool MaybeObject::IsFailure() {
450 return HAS_FAILURE_TAG(this);
454 bool MaybeObject::IsRetryAfterGC() {
455 return HAS_FAILURE_TAG(this)
456 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
460 bool MaybeObject::IsOutOfMemory() {
461 return HAS_FAILURE_TAG(this)
462 && Failure::cast(this)->IsOutOfMemoryException();
466 bool MaybeObject::IsException() {
467 return this == Failure::Exception();
471 bool MaybeObject::IsTheHole() {
472 return !IsFailure() && ToObjectUnchecked()->IsTheHole();
476 Failure* Failure::cast(MaybeObject* obj) {
477 ASSERT(HAS_FAILURE_TAG(obj));
478 return reinterpret_cast<Failure*>(obj);
482 bool Object::IsJSReceiver() {
483 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
484 return IsHeapObject() &&
485 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
489 bool Object::IsJSObject() {
490 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
491 return IsHeapObject() &&
492 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
496 bool Object::IsJSProxy() {
497 if (!Object::IsHeapObject()) return false;
498 InstanceType type = HeapObject::cast(this)->map()->instance_type();
499 return FIRST_JS_PROXY_TYPE <= type && type <= LAST_JS_PROXY_TYPE;
503 TYPE_CHECKER(JSFunctionProxy, JS_FUNCTION_PROXY_TYPE)
504 TYPE_CHECKER(JSSet, JS_SET_TYPE)
505 TYPE_CHECKER(JSMap, JS_MAP_TYPE)
506 TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
507 TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
508 TYPE_CHECKER(Map, MAP_TYPE)
509 TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE)
510 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
513 bool Object::IsDescriptorArray() {
514 return IsFixedArray();
518 bool Object::IsDeoptimizationInputData() {
519 // Must be a fixed array.
520 if (!IsFixedArray()) return false;
522 // There's no sure way to detect the difference between a fixed array and
523 // a deoptimization data array. Since this is used for asserts we can
524 // check that the length is zero or else the fixed size plus a multiple of
526 int length = FixedArray::cast(this)->length();
527 if (length == 0) return true;
529 length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
530 return length >= 0 &&
531 length % DeoptimizationInputData::kDeoptEntrySize == 0;
535 bool Object::IsDeoptimizationOutputData() {
536 if (!IsFixedArray()) return false;
537 // There's actually no way to see the difference between a fixed array and
538 // a deoptimization data array. Since this is used for asserts we can check
539 // that the length is plausible though.
540 if (FixedArray::cast(this)->length() % 2 != 0) return false;
545 bool Object::IsContext() {
546 if (Object::IsHeapObject()) {
547 Map* map = HeapObject::cast(this)->map();
548 Heap* heap = map->GetHeap();
549 return (map == heap->function_context_map() ||
550 map == heap->catch_context_map() ||
551 map == heap->with_context_map() ||
552 map == heap->global_context_map() ||
553 map == heap->block_context_map());
559 bool Object::IsGlobalContext() {
560 return Object::IsHeapObject() &&
561 HeapObject::cast(this)->map() ==
562 HeapObject::cast(this)->GetHeap()->global_context_map();
566 bool Object::IsSerializedScopeInfo() {
567 return Object::IsHeapObject() &&
568 HeapObject::cast(this)->map() ==
569 HeapObject::cast(this)->GetHeap()->serialized_scope_info_map();
573 TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
576 template <> inline bool Is<JSFunction>(Object* obj) {
577 return obj->IsJSFunction();
581 TYPE_CHECKER(Code, CODE_TYPE)
582 TYPE_CHECKER(Oddball, ODDBALL_TYPE)
583 TYPE_CHECKER(JSGlobalPropertyCell, JS_GLOBAL_PROPERTY_CELL_TYPE)
584 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
585 TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
586 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
589 bool Object::IsStringWrapper() {
590 return IsJSValue() && JSValue::cast(this)->value()->IsString();
594 TYPE_CHECKER(Foreign, FOREIGN_TYPE)
597 bool Object::IsBoolean() {
598 return IsOddball() &&
599 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
603 TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
604 TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
607 template <> inline bool Is<JSArray>(Object* obj) {
608 return obj->IsJSArray();
612 bool Object::IsHashTable() {
613 return Object::IsHeapObject() &&
614 HeapObject::cast(this)->map() ==
615 HeapObject::cast(this)->GetHeap()->hash_table_map();
619 bool Object::IsDictionary() {
620 return IsHashTable() &&
621 this != HeapObject::cast(this)->GetHeap()->symbol_table();
625 bool Object::IsSymbolTable() {
626 return IsHashTable() && this ==
627 HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table();
631 bool Object::IsJSFunctionResultCache() {
632 if (!IsFixedArray()) return false;
633 FixedArray* self = FixedArray::cast(this);
634 int length = self->length();
635 if (length < JSFunctionResultCache::kEntriesIndex) return false;
636 if ((length - JSFunctionResultCache::kEntriesIndex)
637 % JSFunctionResultCache::kEntrySize != 0) {
641 if (FLAG_verify_heap) {
642 reinterpret_cast<JSFunctionResultCache*>(this)->
643 JSFunctionResultCacheVerify();
650 bool Object::IsNormalizedMapCache() {
651 if (!IsFixedArray()) return false;
652 if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
656 if (FLAG_verify_heap) {
657 reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
664 bool Object::IsCompilationCacheTable() {
665 return IsHashTable();
669 bool Object::IsCodeCacheHashTable() {
670 return IsHashTable();
674 bool Object::IsPolymorphicCodeCacheHashTable() {
675 return IsHashTable();
679 bool Object::IsMapCache() {
680 return IsHashTable();
684 bool Object::IsPrimitive() {
685 return IsOddball() || IsNumber() || IsString();
689 bool Object::IsJSGlobalProxy() {
690 bool result = IsHeapObject() &&
691 (HeapObject::cast(this)->map()->instance_type() ==
692 JS_GLOBAL_PROXY_TYPE);
693 ASSERT(!result || IsAccessCheckNeeded());
698 bool Object::IsGlobalObject() {
699 if (!IsHeapObject()) return false;
701 InstanceType type = HeapObject::cast(this)->map()->instance_type();
702 return type == JS_GLOBAL_OBJECT_TYPE ||
703 type == JS_BUILTINS_OBJECT_TYPE;
707 TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
708 TYPE_CHECKER(JSBuiltinsObject, JS_BUILTINS_OBJECT_TYPE)
711 bool Object::IsUndetectableObject() {
712 return IsHeapObject()
713 && HeapObject::cast(this)->map()->is_undetectable();
717 bool Object::IsAccessCheckNeeded() {
718 return IsHeapObject()
719 && HeapObject::cast(this)->map()->is_access_check_needed();
723 bool Object::IsStruct() {
724 if (!IsHeapObject()) return false;
725 switch (HeapObject::cast(this)->map()->instance_type()) {
726 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
727 STRUCT_LIST(MAKE_STRUCT_CASE)
728 #undef MAKE_STRUCT_CASE
729 default: return false;
734 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
735 bool Object::Is##Name() { \
736 return Object::IsHeapObject() \
737 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
739 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
740 #undef MAKE_STRUCT_PREDICATE
743 bool Object::IsUndefined() {
744 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
748 bool Object::IsNull() {
749 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
753 bool Object::IsTheHole() {
754 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
758 bool Object::IsTrue() {
759 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
763 bool Object::IsFalse() {
764 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
768 bool Object::IsArgumentsMarker() {
769 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
773 double Object::Number() {
776 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
777 : reinterpret_cast<HeapNumber*>(this)->value();
781 MaybeObject* Object::ToSmi() {
782 if (IsSmi()) return this;
783 if (IsHeapNumber()) {
784 double value = HeapNumber::cast(this)->value();
785 int int_value = FastD2I(value);
786 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
787 return Smi::FromInt(int_value);
790 return Failure::Exception();
794 bool Object::HasSpecificClassOf(String* name) {
795 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
799 MaybeObject* Object::GetElement(uint32_t index) {
800 // GetElement can trigger a getter which can cause allocation.
801 // This was not always the case. This ASSERT is here to catch
802 // leftover incorrect uses.
803 ASSERT(HEAP->IsAllocationAllowed());
804 return GetElementWithReceiver(this, index);
808 Object* Object::GetElementNoExceptionThrown(uint32_t index) {
809 MaybeObject* maybe = GetElementWithReceiver(this, index);
810 ASSERT(!maybe->IsFailure());
811 Object* result = NULL; // Initialization to please compiler.
812 maybe->ToObject(&result);
817 MaybeObject* Object::GetProperty(String* key) {
818 PropertyAttributes attributes;
819 return GetPropertyWithReceiver(this, key, &attributes);
823 MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
824 return GetPropertyWithReceiver(this, key, attributes);
828 #define FIELD_ADDR(p, offset) \
829 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
831 #define READ_FIELD(p, offset) \
832 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
834 #define WRITE_FIELD(p, offset, value) \
835 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
837 #define WRITE_BARRIER(heap, object, offset, value) \
838 heap->incremental_marking()->RecordWrite( \
839 object, HeapObject::RawField(object, offset), value); \
840 if (heap->InNewSpace(value)) { \
841 heap->RecordWrite(object->address(), offset); \
844 #define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \
845 if (mode == UPDATE_WRITE_BARRIER) { \
846 heap->incremental_marking()->RecordWrite( \
847 object, HeapObject::RawField(object, offset), value); \
848 if (heap->InNewSpace(value)) { \
849 heap->RecordWrite(object->address(), offset); \
853 #ifndef V8_TARGET_ARCH_MIPS
854 #define READ_DOUBLE_FIELD(p, offset) \
855 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
856 #else // V8_TARGET_ARCH_MIPS
857 // Prevent gcc from using load-double (mips ldc1) on (possibly)
858 // non-64-bit aligned HeapNumber::value.
859 static inline double read_double_field(void* p, int offset) {
864 c.u[0] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)));
865 c.u[1] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4)));
868 #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset)
869 #endif // V8_TARGET_ARCH_MIPS
871 #ifndef V8_TARGET_ARCH_MIPS
872 #define WRITE_DOUBLE_FIELD(p, offset, value) \
873 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
874 #else // V8_TARGET_ARCH_MIPS
875 // Prevent gcc from using store-double (mips sdc1) on (possibly)
876 // non-64-bit aligned HeapNumber::value.
877 static inline void write_double_field(void* p, int offset,
884 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0];
885 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1];
887 #define WRITE_DOUBLE_FIELD(p, offset, value) \
888 write_double_field(p, offset, value)
889 #endif // V8_TARGET_ARCH_MIPS
892 #define READ_INT_FIELD(p, offset) \
893 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
895 #define WRITE_INT_FIELD(p, offset, value) \
896 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
898 #define READ_INTPTR_FIELD(p, offset) \
899 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
901 #define WRITE_INTPTR_FIELD(p, offset, value) \
902 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
904 #define READ_UINT32_FIELD(p, offset) \
905 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
907 #define WRITE_UINT32_FIELD(p, offset, value) \
908 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
910 #define READ_SHORT_FIELD(p, offset) \
911 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
913 #define WRITE_SHORT_FIELD(p, offset, value) \
914 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
916 #define READ_BYTE_FIELD(p, offset) \
917 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
919 #define WRITE_BYTE_FIELD(p, offset, value) \
920 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
923 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
924 return &READ_FIELD(obj, byte_offset);
929 return Internals::SmiValue(this);
933 Smi* Smi::FromInt(int value) {
934 ASSERT(Smi::IsValid(value));
935 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
936 intptr_t tagged_value =
937 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
938 return reinterpret_cast<Smi*>(tagged_value);
942 Smi* Smi::FromIntptr(intptr_t value) {
943 ASSERT(Smi::IsValid(value));
944 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
945 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
949 Failure::Type Failure::type() const {
950 return static_cast<Type>(value() & kFailureTypeTagMask);
954 bool Failure::IsInternalError() const {
955 return type() == INTERNAL_ERROR;
959 bool Failure::IsOutOfMemoryException() const {
960 return type() == OUT_OF_MEMORY_EXCEPTION;
964 AllocationSpace Failure::allocation_space() const {
965 ASSERT_EQ(RETRY_AFTER_GC, type());
966 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
971 Failure* Failure::InternalError() {
972 return Construct(INTERNAL_ERROR);
976 Failure* Failure::Exception() {
977 return Construct(EXCEPTION);
981 Failure* Failure::OutOfMemoryException() {
982 return Construct(OUT_OF_MEMORY_EXCEPTION);
986 intptr_t Failure::value() const {
987 return static_cast<intptr_t>(
988 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
992 Failure* Failure::RetryAfterGC() {
993 return RetryAfterGC(NEW_SPACE);
997 Failure* Failure::RetryAfterGC(AllocationSpace space) {
998 ASSERT((space & ~kSpaceTagMask) == 0);
999 return Construct(RETRY_AFTER_GC, space);
1003 Failure* Failure::Construct(Type type, intptr_t value) {
1005 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
1006 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
1007 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
1011 bool Smi::IsValid(intptr_t value) {
1013 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
1016 #ifdef V8_TARGET_ARCH_X64
1017 // To be representable as a long smi, the value must be a 32-bit integer.
1018 bool result = (value == static_cast<int32_t>(value));
1020 // To be representable as an tagged small integer, the two
1021 // most-significant bits of 'value' must be either 00 or 11 due to
1022 // sign-extension. To check this we add 01 to the two
1023 // most-significant bits, and check if the most-significant bit is 0
1025 // CAUTION: The original code below:
1026 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
1027 // may lead to incorrect results according to the C language spec, and
1028 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
1029 // compiler may produce undefined results in case of signed integer
1030 // overflow. The computation must be done w/ unsigned ints.
1031 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
1033 ASSERT(result == in_range);
1038 MapWord MapWord::FromMap(Map* map) {
1039 return MapWord(reinterpret_cast<uintptr_t>(map));
1043 Map* MapWord::ToMap() {
1044 return reinterpret_cast<Map*>(value_);
1048 bool MapWord::IsForwardingAddress() {
1049 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
1053 MapWord MapWord::FromForwardingAddress(HeapObject* object) {
1054 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
1055 return MapWord(reinterpret_cast<uintptr_t>(raw));
1059 HeapObject* MapWord::ToForwardingAddress() {
1060 ASSERT(IsForwardingAddress());
1061 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
1066 void HeapObject::VerifyObjectField(int offset) {
1067 VerifyPointer(READ_FIELD(this, offset));
1070 void HeapObject::VerifySmiField(int offset) {
1071 ASSERT(READ_FIELD(this, offset)->IsSmi());
1076 Heap* HeapObject::GetHeap() {
1078 MemoryChunk::FromAddress(reinterpret_cast<Address>(this))->heap();
1079 ASSERT(heap != NULL);
1080 ASSERT(heap->isolate() == Isolate::Current());
1085 Isolate* HeapObject::GetIsolate() {
1086 return GetHeap()->isolate();
1090 Map* HeapObject::map() {
1091 return map_word().ToMap();
1095 void HeapObject::set_map(Map* value) {
1096 set_map_word(MapWord::FromMap(value));
1097 if (value != NULL) {
1098 // TODO(1600) We are passing NULL as a slot because maps can never be on
1099 // evacuation candidate.
1100 value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value);
1105 // Unsafe accessor omitting write barrier.
1106 void HeapObject::set_map_unsafe(Map* value) {
1107 set_map_word(MapWord::FromMap(value));
1111 MapWord HeapObject::map_word() {
1112 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1116 void HeapObject::set_map_word(MapWord map_word) {
1117 // WRITE_FIELD does not invoke write barrier, but there is no need
1119 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1123 HeapObject* HeapObject::FromAddress(Address address) {
1124 ASSERT_TAG_ALIGNED(address);
1125 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1129 Address HeapObject::address() {
1130 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1134 int HeapObject::Size() {
1135 return SizeFromMap(map());
1139 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1140 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1141 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1145 void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1146 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1150 double HeapNumber::value() {
1151 return READ_DOUBLE_FIELD(this, kValueOffset);
1155 void HeapNumber::set_value(double value) {
1156 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1160 int HeapNumber::get_exponent() {
1161 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1162 kExponentShift) - kExponentBias;
1166 int HeapNumber::get_sign() {
1167 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1171 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1174 FixedArrayBase* JSObject::elements() {
1175 Object* array = READ_FIELD(this, kElementsOffset);
1176 return static_cast<FixedArrayBase*>(array);
1179 void JSObject::ValidateSmiOnlyElements() {
1181 if (map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) {
1182 Heap* heap = GetHeap();
1183 // Don't use elements, since integrity checks will fail if there
1184 // are filler pointers in the array.
1185 FixedArray* fixed_array =
1186 reinterpret_cast<FixedArray*>(READ_FIELD(this, kElementsOffset));
1187 Map* map = fixed_array->map();
1188 // Arrays that have been shifted in place can't be verified.
1189 if (map != heap->raw_unchecked_one_pointer_filler_map() &&
1190 map != heap->raw_unchecked_two_pointer_filler_map() &&
1191 map != heap->free_space_map()) {
1192 for (int i = 0; i < fixed_array->length(); i++) {
1193 Object* current = fixed_array->get(i);
1194 ASSERT(current->IsSmi() || current == heap->the_hole_value());
1202 MaybeObject* JSObject::EnsureCanContainNonSmiElements() {
1204 ValidateSmiOnlyElements();
1206 if ((map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS)) {
1208 MaybeObject* maybe_obj = GetElementsTransitionMap(FAST_ELEMENTS);
1209 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1210 set_map(Map::cast(obj));
1216 MaybeObject* JSObject::EnsureCanContainElements(Object** objects,
1218 if (map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) {
1219 for (uint32_t i = 0; i < count; ++i) {
1220 Object* current = *objects++;
1221 if (!current->IsSmi() && current != GetHeap()->the_hole_value()) {
1222 return EnsureCanContainNonSmiElements();
1230 MaybeObject* JSObject::EnsureCanContainElements(FixedArray* elements) {
1231 Object** objects = reinterpret_cast<Object**>(
1232 FIELD_ADDR(elements, elements->OffsetOfElementAt(0)));
1233 return EnsureCanContainElements(objects, elements->length());
1237 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) {
1238 ASSERT((map()->has_fast_elements() ||
1239 map()->has_fast_smi_only_elements()) ==
1240 (value->map() == GetHeap()->fixed_array_map() ||
1241 value->map() == GetHeap()->fixed_cow_array_map()));
1242 ASSERT(map()->has_fast_double_elements() ==
1243 value->IsFixedDoubleArray());
1244 ASSERT(value->HasValidElements());
1246 ValidateSmiOnlyElements();
1248 WRITE_FIELD(this, kElementsOffset, value);
1249 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode);
1253 void JSObject::initialize_properties() {
1254 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1255 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
1259 void JSObject::initialize_elements() {
1260 ASSERT(map()->has_fast_elements() || map()->has_fast_smi_only_elements());
1261 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1262 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array());
1266 MaybeObject* JSObject::ResetElements() {
1268 ElementsKind elements_kind = FLAG_smi_only_arrays
1269 ? FAST_SMI_ONLY_ELEMENTS
1271 MaybeObject* maybe_obj = GetElementsTransitionMap(elements_kind);
1272 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1273 set_map(Map::cast(obj));
1274 initialize_elements();
1279 ACCESSORS(Oddball, to_string, String, kToStringOffset)
1280 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1283 byte Oddball::kind() {
1284 return Smi::cast(READ_FIELD(this, kKindOffset))->value();
1288 void Oddball::set_kind(byte value) {
1289 WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
1293 Object* JSGlobalPropertyCell::value() {
1294 return READ_FIELD(this, kValueOffset);
1298 void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1299 // The write barrier is not used for global property cells.
1300 ASSERT(!val->IsJSGlobalPropertyCell());
1301 WRITE_FIELD(this, kValueOffset, val);
1302 GetHeap()->incremental_marking()->RecordWrite(
1303 this, HeapObject::RawField(this, kValueOffset), val);
1307 int JSObject::GetHeaderSize() {
1308 InstanceType type = map()->instance_type();
1309 // Check for the most common kind of JavaScript object before
1310 // falling into the generic switch. This speeds up the internal
1311 // field operations considerably on average.
1312 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1314 case JS_GLOBAL_PROXY_TYPE:
1315 return JSGlobalProxy::kSize;
1316 case JS_GLOBAL_OBJECT_TYPE:
1317 return JSGlobalObject::kSize;
1318 case JS_BUILTINS_OBJECT_TYPE:
1319 return JSBuiltinsObject::kSize;
1320 case JS_FUNCTION_TYPE:
1321 return JSFunction::kSize;
1323 return JSValue::kSize;
1325 return JSValue::kSize;
1326 case JS_WEAK_MAP_TYPE:
1327 return JSWeakMap::kSize;
1328 case JS_REGEXP_TYPE:
1329 return JSValue::kSize;
1330 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1331 return JSObject::kHeaderSize;
1332 case JS_MESSAGE_OBJECT_TYPE:
1333 return JSMessageObject::kSize;
1341 int JSObject::GetInternalFieldCount() {
1342 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1343 // Make sure to adjust for the number of in-object properties. These
1344 // properties do contribute to the size, but are not internal fields.
1345 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1346 map()->inobject_properties();
1350 int JSObject::GetInternalFieldOffset(int index) {
1351 ASSERT(index < GetInternalFieldCount() && index >= 0);
1352 return GetHeaderSize() + (kPointerSize * index);
1356 Object* JSObject::GetInternalField(int index) {
1357 ASSERT(index < GetInternalFieldCount() && index >= 0);
1358 // Internal objects do follow immediately after the header, whereas in-object
1359 // properties are at the end of the object. Therefore there is no need
1360 // to adjust the index here.
1361 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1365 void JSObject::SetInternalField(int index, Object* value) {
1366 ASSERT(index < GetInternalFieldCount() && index >= 0);
1367 // Internal objects do follow immediately after the header, whereas in-object
1368 // properties are at the end of the object. Therefore there is no need
1369 // to adjust the index here.
1370 int offset = GetHeaderSize() + (kPointerSize * index);
1371 WRITE_FIELD(this, offset, value);
1372 WRITE_BARRIER(GetHeap(), this, offset, value);
1376 // Access fast-case object properties at index. The use of these routines
1377 // is needed to correctly distinguish between properties stored in-object and
1378 // properties stored in the properties array.
1379 Object* JSObject::FastPropertyAt(int index) {
1380 // Adjust for the number of properties stored in the object.
1381 index -= map()->inobject_properties();
1383 int offset = map()->instance_size() + (index * kPointerSize);
1384 return READ_FIELD(this, offset);
1386 ASSERT(index < properties()->length());
1387 return properties()->get(index);
1392 Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1393 // Adjust for the number of properties stored in the object.
1394 index -= map()->inobject_properties();
1396 int offset = map()->instance_size() + (index * kPointerSize);
1397 WRITE_FIELD(this, offset, value);
1398 WRITE_BARRIER(GetHeap(), this, offset, value);
1400 ASSERT(index < properties()->length());
1401 properties()->set(index, value);
1407 int JSObject::GetInObjectPropertyOffset(int index) {
1408 // Adjust for the number of properties stored in the object.
1409 index -= map()->inobject_properties();
1411 return map()->instance_size() + (index * kPointerSize);
1415 Object* JSObject::InObjectPropertyAt(int index) {
1416 // Adjust for the number of properties stored in the object.
1417 index -= map()->inobject_properties();
1419 int offset = map()->instance_size() + (index * kPointerSize);
1420 return READ_FIELD(this, offset);
1424 Object* JSObject::InObjectPropertyAtPut(int index,
1426 WriteBarrierMode mode) {
1427 // Adjust for the number of properties stored in the object.
1428 index -= map()->inobject_properties();
1430 int offset = map()->instance_size() + (index * kPointerSize);
1431 WRITE_FIELD(this, offset, value);
1432 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
1438 void JSObject::InitializeBody(Map* map,
1439 Object* pre_allocated_value,
1440 Object* filler_value) {
1441 ASSERT(!filler_value->IsHeapObject() ||
1442 !GetHeap()->InNewSpace(filler_value));
1443 ASSERT(!pre_allocated_value->IsHeapObject() ||
1444 !GetHeap()->InNewSpace(pre_allocated_value));
1445 int size = map->instance_size();
1446 int offset = kHeaderSize;
1447 if (filler_value != pre_allocated_value) {
1448 int pre_allocated = map->pre_allocated_property_fields();
1449 ASSERT(pre_allocated * kPointerSize + kHeaderSize <= size);
1450 for (int i = 0; i < pre_allocated; i++) {
1451 WRITE_FIELD(this, offset, pre_allocated_value);
1452 offset += kPointerSize;
1455 while (offset < size) {
1456 WRITE_FIELD(this, offset, filler_value);
1457 offset += kPointerSize;
1462 bool JSObject::HasFastProperties() {
1463 return !properties()->IsDictionary();
1467 int JSObject::MaxFastProperties() {
1468 // Allow extra fast properties if the object has more than
1469 // kMaxFastProperties in-object properties. When this is the case,
1470 // it is very unlikely that the object is being used as a dictionary
1471 // and there is a good chance that allowing more map transitions
1472 // will be worth it.
1473 return Max(map()->inobject_properties(), kMaxFastProperties);
1477 void Struct::InitializeBody(int object_size) {
1478 Object* value = GetHeap()->undefined_value();
1479 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1480 WRITE_FIELD(this, offset, value);
1485 bool Object::ToArrayIndex(uint32_t* index) {
1487 int value = Smi::cast(this)->value();
1488 if (value < 0) return false;
1492 if (IsHeapNumber()) {
1493 double value = HeapNumber::cast(this)->value();
1494 uint32_t uint_value = static_cast<uint32_t>(value);
1495 if (value == static_cast<double>(uint_value)) {
1496 *index = uint_value;
1504 bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1505 if (!this->IsJSValue()) return false;
1507 JSValue* js_value = JSValue::cast(this);
1508 if (!js_value->value()->IsString()) return false;
1510 String* str = String::cast(js_value->value());
1511 if (index >= (uint32_t)str->length()) return false;
1517 FixedArrayBase* FixedArrayBase::cast(Object* object) {
1518 ASSERT(object->IsFixedArray() || object->IsFixedDoubleArray());
1519 return reinterpret_cast<FixedArrayBase*>(object);
1523 Object* FixedArray::get(int index) {
1524 ASSERT(index >= 0 && index < this->length());
1525 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1529 void FixedArray::set(int index, Smi* value) {
1530 ASSERT(map() != HEAP->fixed_cow_array_map());
1531 ASSERT(index >= 0 && index < this->length());
1532 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1533 int offset = kHeaderSize + index * kPointerSize;
1534 WRITE_FIELD(this, offset, value);
1538 void FixedArray::set(int index, Object* value) {
1539 ASSERT(map() != HEAP->fixed_cow_array_map());
1540 ASSERT(index >= 0 && index < this->length());
1541 int offset = kHeaderSize + index * kPointerSize;
1542 WRITE_FIELD(this, offset, value);
1543 WRITE_BARRIER(GetHeap(), this, offset, value);
1547 inline bool FixedDoubleArray::is_the_hole_nan(double value) {
1548 return BitCast<uint64_t, double>(value) == kHoleNanInt64;
1552 inline double FixedDoubleArray::hole_nan_as_double() {
1553 return BitCast<double, uint64_t>(kHoleNanInt64);
1557 inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
1558 ASSERT(BitCast<uint64_t>(OS::nan_value()) != kHoleNanInt64);
1559 ASSERT((BitCast<uint64_t>(OS::nan_value()) >> 32) != kHoleNanUpper32);
1560 return OS::nan_value();
1564 double FixedDoubleArray::get_scalar(int index) {
1565 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1566 map() != HEAP->fixed_array_map());
1567 ASSERT(index >= 0 && index < this->length());
1568 double result = READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
1569 ASSERT(!is_the_hole_nan(result));
1574 MaybeObject* FixedDoubleArray::get(int index) {
1575 if (is_the_hole(index)) {
1576 return GetHeap()->the_hole_value();
1578 return GetHeap()->NumberFromDouble(get_scalar(index));
1583 void FixedDoubleArray::set(int index, double value) {
1584 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1585 map() != HEAP->fixed_array_map());
1586 int offset = kHeaderSize + index * kDoubleSize;
1587 if (isnan(value)) value = canonical_not_the_hole_nan_as_double();
1588 WRITE_DOUBLE_FIELD(this, offset, value);
1592 void FixedDoubleArray::set_the_hole(int index) {
1593 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1594 map() != HEAP->fixed_array_map());
1595 int offset = kHeaderSize + index * kDoubleSize;
1596 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1600 bool FixedDoubleArray::is_the_hole(int index) {
1601 int offset = kHeaderSize + index * kDoubleSize;
1602 return is_the_hole_nan(READ_DOUBLE_FIELD(this, offset));
1606 void FixedDoubleArray::Initialize(FixedDoubleArray* from) {
1607 int old_length = from->length();
1608 ASSERT(old_length < length());
1609 if (old_length * kDoubleSize >= OS::kMinComplexMemCopy) {
1610 OS::MemCopy(FIELD_ADDR(this, kHeaderSize),
1611 FIELD_ADDR(from, kHeaderSize),
1612 old_length * kDoubleSize);
1614 for (int i = 0; i < old_length; ++i) {
1615 if (from->is_the_hole(i)) {
1618 set(i, from->get_scalar(i));
1622 int offset = kHeaderSize + old_length * kDoubleSize;
1623 for (int current = from->length(); current < length(); ++current) {
1624 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1625 offset += kDoubleSize;
1630 void FixedDoubleArray::Initialize(FixedArray* from) {
1631 int old_length = from->length();
1632 ASSERT(old_length <= length());
1633 for (int i = 0; i < old_length; i++) {
1634 Object* hole_or_object = from->get(i);
1635 if (hole_or_object->IsTheHole()) {
1638 set(i, hole_or_object->Number());
1641 int offset = kHeaderSize + old_length * kDoubleSize;
1642 for (int current = from->length(); current < length(); ++current) {
1643 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1644 offset += kDoubleSize;
1649 void FixedDoubleArray::Initialize(NumberDictionary* from) {
1650 int offset = kHeaderSize;
1651 for (int current = 0; current < length(); ++current) {
1652 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1653 offset += kDoubleSize;
1655 for (int i = 0; i < from->Capacity(); i++) {
1656 Object* key = from->KeyAt(i);
1657 if (key->IsNumber()) {
1658 uint32_t entry = static_cast<uint32_t>(key->Number());
1659 set(entry, from->ValueAt(i)->Number());
1665 WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
1666 Heap* heap = GetHeap();
1667 if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
1668 if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER;
1669 return UPDATE_WRITE_BARRIER;
1673 void FixedArray::set(int index,
1675 WriteBarrierMode mode) {
1676 ASSERT(map() != HEAP->fixed_cow_array_map());
1677 ASSERT(index >= 0 && index < this->length());
1678 int offset = kHeaderSize + index * kPointerSize;
1679 WRITE_FIELD(this, offset, value);
1680 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
1684 void FixedArray::NoWriteBarrierSet(FixedArray* array,
1687 ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
1688 ASSERT(index >= 0 && index < array->length());
1689 ASSERT(!HEAP->InNewSpace(value));
1690 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1694 void FixedArray::set_undefined(int index) {
1695 ASSERT(map() != HEAP->fixed_cow_array_map());
1696 set_undefined(GetHeap(), index);
1700 void FixedArray::set_undefined(Heap* heap, int index) {
1701 ASSERT(index >= 0 && index < this->length());
1702 ASSERT(!heap->InNewSpace(heap->undefined_value()));
1703 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1704 heap->undefined_value());
1708 void FixedArray::set_null(int index) {
1709 set_null(GetHeap(), index);
1713 void FixedArray::set_null(Heap* heap, int index) {
1714 ASSERT(index >= 0 && index < this->length());
1715 ASSERT(!heap->InNewSpace(heap->null_value()));
1716 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
1720 void FixedArray::set_the_hole(int index) {
1721 ASSERT(map() != HEAP->fixed_cow_array_map());
1722 ASSERT(index >= 0 && index < this->length());
1723 ASSERT(!HEAP->InNewSpace(HEAP->the_hole_value()));
1725 kHeaderSize + index * kPointerSize,
1726 GetHeap()->the_hole_value());
1730 void FixedArray::set_unchecked(int index, Smi* value) {
1731 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1732 int offset = kHeaderSize + index * kPointerSize;
1733 WRITE_FIELD(this, offset, value);
1737 void FixedArray::set_unchecked(Heap* heap,
1740 WriteBarrierMode mode) {
1741 int offset = kHeaderSize + index * kPointerSize;
1742 WRITE_FIELD(this, offset, value);
1743 CONDITIONAL_WRITE_BARRIER(heap, this, offset, value, mode);
1747 void FixedArray::set_null_unchecked(Heap* heap, int index) {
1748 ASSERT(index >= 0 && index < this->length());
1749 ASSERT(!HEAP->InNewSpace(heap->null_value()));
1750 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
1754 Object** FixedArray::data_start() {
1755 return HeapObject::RawField(this, kHeaderSize);
1759 bool DescriptorArray::IsEmpty() {
1760 ASSERT(this->IsSmi() ||
1761 this->length() > kFirstIndex ||
1762 this == HEAP->empty_descriptor_array());
1763 return this->IsSmi() || length() <= kFirstIndex;
1767 int DescriptorArray::bit_field3_storage() {
1768 Object* storage = READ_FIELD(this, kBitField3StorageOffset);
1769 return Smi::cast(storage)->value();
1772 void DescriptorArray::set_bit_field3_storage(int value) {
1774 WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value));
1778 void DescriptorArray::NoWriteBarrierSwap(FixedArray* array,
1781 Object* tmp = array->get(first);
1782 NoWriteBarrierSet(array, first, array->get(second));
1783 NoWriteBarrierSet(array, second, tmp);
1787 int DescriptorArray::Search(String* name) {
1788 SLOW_ASSERT(IsSortedNoDuplicates());
1790 // Check for empty descriptor array.
1791 int nof = number_of_descriptors();
1792 if (nof == 0) return kNotFound;
1794 // Fast case: do linear search for small arrays.
1795 const int kMaxElementsForLinearSearch = 8;
1796 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1797 return LinearSearch(name, nof);
1800 // Slow case: perform binary search.
1801 return BinarySearch(name, 0, nof - 1);
1805 int DescriptorArray::SearchWithCache(String* name) {
1806 int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name);
1807 if (number == DescriptorLookupCache::kAbsent) {
1808 number = Search(name);
1809 GetIsolate()->descriptor_lookup_cache()->Update(this, name, number);
1815 String* DescriptorArray::GetKey(int descriptor_number) {
1816 ASSERT(descriptor_number < number_of_descriptors());
1817 return String::cast(get(ToKeyIndex(descriptor_number)));
1821 Object* DescriptorArray::GetValue(int descriptor_number) {
1822 ASSERT(descriptor_number < number_of_descriptors());
1823 return GetContentArray()->get(ToValueIndex(descriptor_number));
1827 Smi* DescriptorArray::GetDetails(int descriptor_number) {
1828 ASSERT(descriptor_number < number_of_descriptors());
1829 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1833 PropertyType DescriptorArray::GetType(int descriptor_number) {
1834 ASSERT(descriptor_number < number_of_descriptors());
1835 return PropertyDetails(GetDetails(descriptor_number)).type();
1839 int DescriptorArray::GetFieldIndex(int descriptor_number) {
1840 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1844 JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1845 return JSFunction::cast(GetValue(descriptor_number));
1849 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1850 ASSERT(GetType(descriptor_number) == CALLBACKS);
1851 return GetValue(descriptor_number);
1855 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1856 ASSERT(GetType(descriptor_number) == CALLBACKS);
1857 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number));
1858 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address());
1862 bool DescriptorArray::IsProperty(int descriptor_number) {
1863 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1867 bool DescriptorArray::IsTransition(int descriptor_number) {
1868 PropertyType t = GetType(descriptor_number);
1869 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION ||
1870 t == ELEMENTS_TRANSITION;
1874 bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1875 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1879 bool DescriptorArray::IsDontEnum(int descriptor_number) {
1880 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1884 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1885 desc->Init(GetKey(descriptor_number),
1886 GetValue(descriptor_number),
1887 PropertyDetails(GetDetails(descriptor_number)));
1891 void DescriptorArray::Set(int descriptor_number,
1893 const WhitenessWitness&) {
1895 ASSERT(descriptor_number < number_of_descriptors());
1897 // Make sure none of the elements in desc are in new space.
1898 ASSERT(!HEAP->InNewSpace(desc->GetKey()));
1899 ASSERT(!HEAP->InNewSpace(desc->GetValue()));
1901 NoWriteBarrierSet(this,
1902 ToKeyIndex(descriptor_number),
1904 FixedArray* content_array = GetContentArray();
1905 NoWriteBarrierSet(content_array,
1906 ToValueIndex(descriptor_number),
1908 NoWriteBarrierSet(content_array,
1909 ToDetailsIndex(descriptor_number),
1910 desc->GetDetails().AsSmi());
1914 void DescriptorArray::CopyFrom(int index,
1915 DescriptorArray* src,
1917 const WhitenessWitness& witness) {
1919 src->Get(src_index, &desc);
1920 Set(index, &desc, witness);
1924 void DescriptorArray::NoWriteBarrierSwapDescriptors(int first, int second) {
1925 NoWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second));
1926 FixedArray* content_array = GetContentArray();
1927 NoWriteBarrierSwap(content_array,
1928 ToValueIndex(first),
1929 ToValueIndex(second));
1930 NoWriteBarrierSwap(content_array,
1931 ToDetailsIndex(first),
1932 ToDetailsIndex(second));
1936 DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
1937 : marking_(array->GetHeap()->incremental_marking()) {
1938 marking_->EnterNoMarkingScope();
1939 if (array->number_of_descriptors() > 0) {
1940 ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT);
1941 ASSERT(Marking::Color(array->GetContentArray()) == Marking::WHITE_OBJECT);
1946 DescriptorArray::WhitenessWitness::~WhitenessWitness() {
1947 marking_->LeaveNoMarkingScope();
1951 template<typename Shape, typename Key>
1952 int HashTable<Shape, Key>::ComputeCapacity(int at_least_space_for) {
1953 const int kMinCapacity = 32;
1954 int capacity = RoundUpToPowerOf2(at_least_space_for * 2);
1955 if (capacity < kMinCapacity) {
1956 capacity = kMinCapacity; // Guarantee min capacity.
1962 template<typename Shape, typename Key>
1963 int HashTable<Shape, Key>::FindEntry(Key key) {
1964 return FindEntry(GetIsolate(), key);
1968 // Find entry for key otherwise return kNotFound.
1969 template<typename Shape, typename Key>
1970 int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
1971 uint32_t capacity = Capacity();
1972 uint32_t entry = FirstProbe(Shape::Hash(key), capacity);
1974 // EnsureCapacity will guarantee the hash table is never full.
1976 Object* element = KeyAt(entry);
1977 if (element == isolate->heap()->undefined_value()) break; // Empty entry.
1978 if (element != isolate->heap()->null_value() &&
1979 Shape::IsMatch(key, element)) return entry;
1980 entry = NextProbe(entry, count++, capacity);
1986 bool NumberDictionary::requires_slow_elements() {
1987 Object* max_index_object = get(kMaxNumberKeyIndex);
1988 if (!max_index_object->IsSmi()) return false;
1990 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1993 uint32_t NumberDictionary::max_number_key() {
1994 ASSERT(!requires_slow_elements());
1995 Object* max_index_object = get(kMaxNumberKeyIndex);
1996 if (!max_index_object->IsSmi()) return 0;
1997 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1998 return value >> kRequiresSlowElementsTagSize;
2001 void NumberDictionary::set_requires_slow_elements() {
2002 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
2006 // ------------------------------------
2010 CAST_ACCESSOR(FixedArray)
2011 CAST_ACCESSOR(FixedDoubleArray)
2012 CAST_ACCESSOR(DescriptorArray)
2013 CAST_ACCESSOR(DeoptimizationInputData)
2014 CAST_ACCESSOR(DeoptimizationOutputData)
2015 CAST_ACCESSOR(SymbolTable)
2016 CAST_ACCESSOR(JSFunctionResultCache)
2017 CAST_ACCESSOR(NormalizedMapCache)
2018 CAST_ACCESSOR(CompilationCacheTable)
2019 CAST_ACCESSOR(CodeCacheHashTable)
2020 CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
2021 CAST_ACCESSOR(MapCache)
2022 CAST_ACCESSOR(String)
2023 CAST_ACCESSOR(SeqString)
2024 CAST_ACCESSOR(SeqAsciiString)
2025 CAST_ACCESSOR(SeqTwoByteString)
2026 CAST_ACCESSOR(SlicedString)
2027 CAST_ACCESSOR(ConsString)
2028 CAST_ACCESSOR(ExternalString)
2029 CAST_ACCESSOR(ExternalAsciiString)
2030 CAST_ACCESSOR(ExternalTwoByteString)
2031 CAST_ACCESSOR(JSReceiver)
2032 CAST_ACCESSOR(JSObject)
2034 CAST_ACCESSOR(HeapObject)
2035 CAST_ACCESSOR(HeapNumber)
2036 CAST_ACCESSOR(Oddball)
2037 CAST_ACCESSOR(JSGlobalPropertyCell)
2038 CAST_ACCESSOR(SharedFunctionInfo)
2040 CAST_ACCESSOR(JSFunction)
2041 CAST_ACCESSOR(GlobalObject)
2042 CAST_ACCESSOR(JSGlobalProxy)
2043 CAST_ACCESSOR(JSGlobalObject)
2044 CAST_ACCESSOR(JSBuiltinsObject)
2046 CAST_ACCESSOR(JSArray)
2047 CAST_ACCESSOR(JSRegExp)
2048 CAST_ACCESSOR(JSProxy)
2049 CAST_ACCESSOR(JSFunctionProxy)
2050 CAST_ACCESSOR(JSSet)
2051 CAST_ACCESSOR(JSMap)
2052 CAST_ACCESSOR(JSWeakMap)
2053 CAST_ACCESSOR(Foreign)
2054 CAST_ACCESSOR(ByteArray)
2055 CAST_ACCESSOR(FreeSpace)
2056 CAST_ACCESSOR(ExternalArray)
2057 CAST_ACCESSOR(ExternalByteArray)
2058 CAST_ACCESSOR(ExternalUnsignedByteArray)
2059 CAST_ACCESSOR(ExternalShortArray)
2060 CAST_ACCESSOR(ExternalUnsignedShortArray)
2061 CAST_ACCESSOR(ExternalIntArray)
2062 CAST_ACCESSOR(ExternalUnsignedIntArray)
2063 CAST_ACCESSOR(ExternalFloatArray)
2064 CAST_ACCESSOR(ExternalDoubleArray)
2065 CAST_ACCESSOR(ExternalPixelArray)
2066 CAST_ACCESSOR(Struct)
2069 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
2070 STRUCT_LIST(MAKE_STRUCT_CAST)
2071 #undef MAKE_STRUCT_CAST
2074 template <typename Shape, typename Key>
2075 HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
2076 ASSERT(obj->IsHashTable());
2077 return reinterpret_cast<HashTable*>(obj);
2081 SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
2082 SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
2084 SMI_ACCESSORS(String, length, kLengthOffset)
2085 SMI_ACCESSORS(SeqString, symbol_id, kSymbolIdOffset)
2088 uint32_t String::hash_field() {
2089 return READ_UINT32_FIELD(this, kHashFieldOffset);
2093 void String::set_hash_field(uint32_t value) {
2094 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
2095 #if V8_HOST_ARCH_64_BIT
2096 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
2101 bool String::Equals(String* other) {
2102 if (other == this) return true;
2103 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
2106 return SlowEquals(other);
2110 MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
2111 if (!StringShape(this).IsCons()) return this;
2112 ConsString* cons = ConsString::cast(this);
2113 if (cons->IsFlat()) return cons->first();
2114 return SlowTryFlatten(pretenure);
2118 String* String::TryFlattenGetString(PretenureFlag pretenure) {
2119 MaybeObject* flat = TryFlatten(pretenure);
2120 Object* successfully_flattened;
2121 if (!flat->ToObject(&successfully_flattened)) return this;
2122 return String::cast(successfully_flattened);
2126 uint16_t String::Get(int index) {
2127 ASSERT(index >= 0 && index < length());
2128 switch (StringShape(this).full_representation_tag()) {
2129 case kSeqStringTag | kAsciiStringTag:
2130 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
2131 case kSeqStringTag | kTwoByteStringTag:
2132 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
2133 case kConsStringTag | kAsciiStringTag:
2134 case kConsStringTag | kTwoByteStringTag:
2135 return ConsString::cast(this)->ConsStringGet(index);
2136 case kExternalStringTag | kAsciiStringTag:
2137 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
2138 case kExternalStringTag | kTwoByteStringTag:
2139 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
2140 case kSlicedStringTag | kAsciiStringTag:
2141 case kSlicedStringTag | kTwoByteStringTag:
2142 return SlicedString::cast(this)->SlicedStringGet(index);
2152 void String::Set(int index, uint16_t value) {
2153 ASSERT(index >= 0 && index < length());
2154 ASSERT(StringShape(this).IsSequential());
2156 return this->IsAsciiRepresentation()
2157 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
2158 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
2162 bool String::IsFlat() {
2163 if (!StringShape(this).IsCons()) return true;
2164 return ConsString::cast(this)->second()->length() == 0;
2168 String* String::GetUnderlying() {
2169 // Giving direct access to underlying string only makes sense if the
2170 // wrapping string is already flattened.
2171 ASSERT(this->IsFlat());
2172 ASSERT(StringShape(this).IsIndirect());
2173 STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
2174 const int kUnderlyingOffset = SlicedString::kParentOffset;
2175 return String::cast(READ_FIELD(this, kUnderlyingOffset));
2179 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
2180 ASSERT(index >= 0 && index < length());
2181 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2185 void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
2186 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
2187 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
2188 static_cast<byte>(value));
2192 Address SeqAsciiString::GetCharsAddress() {
2193 return FIELD_ADDR(this, kHeaderSize);
2197 char* SeqAsciiString::GetChars() {
2198 return reinterpret_cast<char*>(GetCharsAddress());
2202 Address SeqTwoByteString::GetCharsAddress() {
2203 return FIELD_ADDR(this, kHeaderSize);
2207 uc16* SeqTwoByteString::GetChars() {
2208 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
2212 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
2213 ASSERT(index >= 0 && index < length());
2214 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
2218 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
2219 ASSERT(index >= 0 && index < length());
2220 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
2224 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
2225 return SizeFor(length());
2229 int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
2230 return SizeFor(length());
2234 String* SlicedString::parent() {
2235 return String::cast(READ_FIELD(this, kParentOffset));
2239 void SlicedString::set_parent(String* parent) {
2240 ASSERT(parent->IsSeqString() || parent->IsExternalString());
2241 WRITE_FIELD(this, kParentOffset, parent);
2245 SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
2248 String* ConsString::first() {
2249 return String::cast(READ_FIELD(this, kFirstOffset));
2253 Object* ConsString::unchecked_first() {
2254 return READ_FIELD(this, kFirstOffset);
2258 void ConsString::set_first(String* value, WriteBarrierMode mode) {
2259 WRITE_FIELD(this, kFirstOffset, value);
2260 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode);
2264 String* ConsString::second() {
2265 return String::cast(READ_FIELD(this, kSecondOffset));
2269 Object* ConsString::unchecked_second() {
2270 return READ_FIELD(this, kSecondOffset);
2274 void ConsString::set_second(String* value, WriteBarrierMode mode) {
2275 WRITE_FIELD(this, kSecondOffset, value);
2276 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode);
2280 const ExternalAsciiString::Resource* ExternalAsciiString::resource() {
2281 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2285 void ExternalAsciiString::set_resource(
2286 const ExternalAsciiString::Resource* resource) {
2287 *reinterpret_cast<const Resource**>(
2288 FIELD_ADDR(this, kResourceOffset)) = resource;
2292 const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
2293 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2297 void ExternalTwoByteString::set_resource(
2298 const ExternalTwoByteString::Resource* resource) {
2299 *reinterpret_cast<const Resource**>(
2300 FIELD_ADDR(this, kResourceOffset)) = resource;
2304 void JSFunctionResultCache::MakeZeroSize() {
2305 set_finger_index(kEntriesIndex);
2306 set_size(kEntriesIndex);
2310 void JSFunctionResultCache::Clear() {
2311 int cache_size = size();
2312 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
2313 MemsetPointer(entries_start,
2314 GetHeap()->the_hole_value(),
2315 cache_size - kEntriesIndex);
2320 int JSFunctionResultCache::size() {
2321 return Smi::cast(get(kCacheSizeIndex))->value();
2325 void JSFunctionResultCache::set_size(int size) {
2326 set(kCacheSizeIndex, Smi::FromInt(size));
2330 int JSFunctionResultCache::finger_index() {
2331 return Smi::cast(get(kFingerIndex))->value();
2335 void JSFunctionResultCache::set_finger_index(int finger_index) {
2336 set(kFingerIndex, Smi::FromInt(finger_index));
2340 byte ByteArray::get(int index) {
2341 ASSERT(index >= 0 && index < this->length());
2342 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2346 void ByteArray::set(int index, byte value) {
2347 ASSERT(index >= 0 && index < this->length());
2348 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2352 int ByteArray::get_int(int index) {
2353 ASSERT(index >= 0 && (index * kIntSize) < this->length());
2354 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2358 ByteArray* ByteArray::FromDataStartAddress(Address address) {
2359 ASSERT_TAG_ALIGNED(address);
2360 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2364 Address ByteArray::GetDataStartAddress() {
2365 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2369 uint8_t* ExternalPixelArray::external_pixel_pointer() {
2370 return reinterpret_cast<uint8_t*>(external_pointer());
2374 uint8_t ExternalPixelArray::get_scalar(int index) {
2375 ASSERT((index >= 0) && (index < this->length()));
2376 uint8_t* ptr = external_pixel_pointer();
2381 MaybeObject* ExternalPixelArray::get(int index) {
2382 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2386 void ExternalPixelArray::set(int index, uint8_t value) {
2387 ASSERT((index >= 0) && (index < this->length()));
2388 uint8_t* ptr = external_pixel_pointer();
2393 void* ExternalArray::external_pointer() {
2394 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2395 return reinterpret_cast<void*>(ptr);
2399 void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2400 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2401 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2405 int8_t ExternalByteArray::get_scalar(int index) {
2406 ASSERT((index >= 0) && (index < this->length()));
2407 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2412 MaybeObject* ExternalByteArray::get(int index) {
2413 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2417 void ExternalByteArray::set(int index, int8_t value) {
2418 ASSERT((index >= 0) && (index < this->length()));
2419 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2424 uint8_t ExternalUnsignedByteArray::get_scalar(int index) {
2425 ASSERT((index >= 0) && (index < this->length()));
2426 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2431 MaybeObject* ExternalUnsignedByteArray::get(int index) {
2432 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2436 void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2437 ASSERT((index >= 0) && (index < this->length()));
2438 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2443 int16_t ExternalShortArray::get_scalar(int index) {
2444 ASSERT((index >= 0) && (index < this->length()));
2445 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2450 MaybeObject* ExternalShortArray::get(int index) {
2451 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2455 void ExternalShortArray::set(int index, int16_t value) {
2456 ASSERT((index >= 0) && (index < this->length()));
2457 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2462 uint16_t ExternalUnsignedShortArray::get_scalar(int index) {
2463 ASSERT((index >= 0) && (index < this->length()));
2464 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2469 MaybeObject* ExternalUnsignedShortArray::get(int index) {
2470 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2474 void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2475 ASSERT((index >= 0) && (index < this->length()));
2476 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2481 int32_t ExternalIntArray::get_scalar(int index) {
2482 ASSERT((index >= 0) && (index < this->length()));
2483 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2488 MaybeObject* ExternalIntArray::get(int index) {
2489 return GetHeap()->NumberFromInt32(get_scalar(index));
2493 void ExternalIntArray::set(int index, int32_t value) {
2494 ASSERT((index >= 0) && (index < this->length()));
2495 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2500 uint32_t ExternalUnsignedIntArray::get_scalar(int index) {
2501 ASSERT((index >= 0) && (index < this->length()));
2502 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2507 MaybeObject* ExternalUnsignedIntArray::get(int index) {
2508 return GetHeap()->NumberFromUint32(get_scalar(index));
2512 void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2513 ASSERT((index >= 0) && (index < this->length()));
2514 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2519 float ExternalFloatArray::get_scalar(int index) {
2520 ASSERT((index >= 0) && (index < this->length()));
2521 float* ptr = static_cast<float*>(external_pointer());
2526 MaybeObject* ExternalFloatArray::get(int index) {
2527 return GetHeap()->NumberFromDouble(get_scalar(index));
2531 void ExternalFloatArray::set(int index, float value) {
2532 ASSERT((index >= 0) && (index < this->length()));
2533 float* ptr = static_cast<float*>(external_pointer());
2538 double ExternalDoubleArray::get_scalar(int index) {
2539 ASSERT((index >= 0) && (index < this->length()));
2540 double* ptr = static_cast<double*>(external_pointer());
2545 MaybeObject* ExternalDoubleArray::get(int index) {
2546 return GetHeap()->NumberFromDouble(get_scalar(index));
2550 void ExternalDoubleArray::set(int index, double value) {
2551 ASSERT((index >= 0) && (index < this->length()));
2552 double* ptr = static_cast<double*>(external_pointer());
2557 int Map::visitor_id() {
2558 return READ_BYTE_FIELD(this, kVisitorIdOffset);
2562 void Map::set_visitor_id(int id) {
2563 ASSERT(0 <= id && id < 256);
2564 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2568 int Map::instance_size() {
2569 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2573 int Map::inobject_properties() {
2574 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2578 int Map::pre_allocated_property_fields() {
2579 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2583 int HeapObject::SizeFromMap(Map* map) {
2584 int instance_size = map->instance_size();
2585 if (instance_size != kVariableSizeSentinel) return instance_size;
2586 // We can ignore the "symbol" bit becase it is only set for symbols
2587 // and implies a string type.
2588 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
2589 // Only inline the most frequent cases.
2590 if (instance_type == FIXED_ARRAY_TYPE) {
2591 return FixedArray::BodyDescriptor::SizeOf(map, this);
2593 if (instance_type == ASCII_STRING_TYPE) {
2594 return SeqAsciiString::SizeFor(
2595 reinterpret_cast<SeqAsciiString*>(this)->length());
2597 if (instance_type == BYTE_ARRAY_TYPE) {
2598 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2600 if (instance_type == FREE_SPACE_TYPE) {
2601 return reinterpret_cast<FreeSpace*>(this)->size();
2603 if (instance_type == STRING_TYPE) {
2604 return SeqTwoByteString::SizeFor(
2605 reinterpret_cast<SeqTwoByteString*>(this)->length());
2607 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
2608 return FixedDoubleArray::SizeFor(
2609 reinterpret_cast<FixedDoubleArray*>(this)->length());
2611 ASSERT(instance_type == CODE_TYPE);
2612 return reinterpret_cast<Code*>(this)->CodeSize();
2616 void Map::set_instance_size(int value) {
2617 ASSERT_EQ(0, value & (kPointerSize - 1));
2618 value >>= kPointerSizeLog2;
2619 ASSERT(0 <= value && value < 256);
2620 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2624 void Map::set_inobject_properties(int value) {
2625 ASSERT(0 <= value && value < 256);
2626 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2630 void Map::set_pre_allocated_property_fields(int value) {
2631 ASSERT(0 <= value && value < 256);
2632 WRITE_BYTE_FIELD(this,
2633 kPreAllocatedPropertyFieldsOffset,
2634 static_cast<byte>(value));
2638 InstanceType Map::instance_type() {
2639 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2643 void Map::set_instance_type(InstanceType value) {
2644 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2648 int Map::unused_property_fields() {
2649 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2653 void Map::set_unused_property_fields(int value) {
2654 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2658 byte Map::bit_field() {
2659 return READ_BYTE_FIELD(this, kBitFieldOffset);
2663 void Map::set_bit_field(byte value) {
2664 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2668 byte Map::bit_field2() {
2669 return READ_BYTE_FIELD(this, kBitField2Offset);
2673 void Map::set_bit_field2(byte value) {
2674 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2678 void Map::set_non_instance_prototype(bool value) {
2680 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2682 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2687 bool Map::has_non_instance_prototype() {
2688 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2692 void Map::set_function_with_prototype(bool value) {
2694 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2696 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2701 bool Map::function_with_prototype() {
2702 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2706 void Map::set_is_access_check_needed(bool access_check_needed) {
2707 if (access_check_needed) {
2708 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2710 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2715 bool Map::is_access_check_needed() {
2716 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2720 void Map::set_is_extensible(bool value) {
2722 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2724 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2728 bool Map::is_extensible() {
2729 return ((1 << kIsExtensible) & bit_field2()) != 0;
2733 void Map::set_attached_to_shared_function_info(bool value) {
2735 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2737 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2741 bool Map::attached_to_shared_function_info() {
2742 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2746 void Map::set_is_shared(bool value) {
2748 set_bit_field3(bit_field3() | (1 << kIsShared));
2750 set_bit_field3(bit_field3() & ~(1 << kIsShared));
2754 bool Map::is_shared() {
2755 return ((1 << kIsShared) & bit_field3()) != 0;
2758 void Map::set_named_interceptor_is_fallback(bool value)
2761 set_bit_field3(bit_field3() | (1 << kNamedInterceptorIsFallback));
2763 set_bit_field3(bit_field3() & ~(1 << kNamedInterceptorIsFallback));
2767 bool Map::named_interceptor_is_fallback()
2769 return ((1 << kNamedInterceptorIsFallback) & bit_field3()) != 0;
2773 JSFunction* Map::unchecked_constructor() {
2774 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2778 Code::Flags Code::flags() {
2779 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2783 void Code::set_flags(Code::Flags flags) {
2784 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
2785 // Make sure that all call stubs have an arguments count.
2786 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2787 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
2788 ExtractArgumentsCountFromFlags(flags) >= 0);
2789 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2793 Code::Kind Code::kind() {
2794 return ExtractKindFromFlags(flags());
2798 InlineCacheState Code::ic_state() {
2799 InlineCacheState result = ExtractICStateFromFlags(flags());
2800 // Only allow uninitialized or debugger states for non-IC code
2801 // objects. This is used in the debugger to determine whether or not
2802 // a call to code object has been replaced with a debug break call.
2803 ASSERT(is_inline_cache_stub() ||
2804 result == UNINITIALIZED ||
2805 result == DEBUG_BREAK ||
2806 result == DEBUG_PREPARE_STEP_IN);
2811 Code::ExtraICState Code::extra_ic_state() {
2812 ASSERT(is_inline_cache_stub());
2813 return ExtractExtraICStateFromFlags(flags());
2817 PropertyType Code::type() {
2818 return ExtractTypeFromFlags(flags());
2822 int Code::arguments_count() {
2823 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
2824 return ExtractArgumentsCountFromFlags(flags());
2828 int Code::major_key() {
2829 ASSERT(kind() == STUB ||
2830 kind() == UNARY_OP_IC ||
2831 kind() == BINARY_OP_IC ||
2832 kind() == COMPARE_IC ||
2833 kind() == TO_BOOLEAN_IC);
2834 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
2838 void Code::set_major_key(int major) {
2839 ASSERT(kind() == STUB ||
2840 kind() == UNARY_OP_IC ||
2841 kind() == BINARY_OP_IC ||
2842 kind() == COMPARE_IC ||
2843 kind() == TO_BOOLEAN_IC);
2844 ASSERT(0 <= major && major < 256);
2845 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2849 bool Code::is_pregenerated() {
2850 return kind() == STUB && IsPregeneratedField::decode(flags());
2854 void Code::set_is_pregenerated(bool value) {
2855 ASSERT(kind() == STUB);
2857 f = static_cast<Flags>(IsPregeneratedField::update(f, value));
2862 bool Code::optimizable() {
2863 ASSERT(kind() == FUNCTION);
2864 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
2868 void Code::set_optimizable(bool value) {
2869 ASSERT(kind() == FUNCTION);
2870 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
2874 bool Code::has_deoptimization_support() {
2875 ASSERT(kind() == FUNCTION);
2876 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2877 return FullCodeFlagsHasDeoptimizationSupportField::decode(flags);
2881 void Code::set_has_deoptimization_support(bool value) {
2882 ASSERT(kind() == FUNCTION);
2883 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2884 flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value);
2885 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
2889 bool Code::has_debug_break_slots() {
2890 ASSERT(kind() == FUNCTION);
2891 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2892 return FullCodeFlagsHasDebugBreakSlotsField::decode(flags);
2896 void Code::set_has_debug_break_slots(bool value) {
2897 ASSERT(kind() == FUNCTION);
2898 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2899 flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value);
2900 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
2904 bool Code::is_compiled_optimizable() {
2905 ASSERT(kind() == FUNCTION);
2906 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2907 return FullCodeFlagsIsCompiledOptimizable::decode(flags);
2911 void Code::set_compiled_optimizable(bool value) {
2912 ASSERT(kind() == FUNCTION);
2913 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2914 flags = FullCodeFlagsIsCompiledOptimizable::update(flags, value);
2915 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
2919 int Code::allow_osr_at_loop_nesting_level() {
2920 ASSERT(kind() == FUNCTION);
2921 return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
2925 void Code::set_allow_osr_at_loop_nesting_level(int level) {
2926 ASSERT(kind() == FUNCTION);
2927 ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
2928 WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
2932 unsigned Code::stack_slots() {
2933 ASSERT(kind() == OPTIMIZED_FUNCTION);
2934 return READ_UINT32_FIELD(this, kStackSlotsOffset);
2938 void Code::set_stack_slots(unsigned slots) {
2939 ASSERT(kind() == OPTIMIZED_FUNCTION);
2940 WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
2944 unsigned Code::safepoint_table_offset() {
2945 ASSERT(kind() == OPTIMIZED_FUNCTION);
2946 return READ_UINT32_FIELD(this, kSafepointTableOffsetOffset);
2950 void Code::set_safepoint_table_offset(unsigned offset) {
2951 ASSERT(kind() == OPTIMIZED_FUNCTION);
2952 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
2953 WRITE_UINT32_FIELD(this, kSafepointTableOffsetOffset, offset);
2957 unsigned Code::stack_check_table_offset() {
2958 ASSERT(kind() == FUNCTION);
2959 return READ_UINT32_FIELD(this, kStackCheckTableOffsetOffset);
2963 void Code::set_stack_check_table_offset(unsigned offset) {
2964 ASSERT(kind() == FUNCTION);
2965 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
2966 WRITE_UINT32_FIELD(this, kStackCheckTableOffsetOffset, offset);
2970 CheckType Code::check_type() {
2971 ASSERT(is_call_stub() || is_keyed_call_stub());
2972 byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
2973 return static_cast<CheckType>(type);
2977 void Code::set_check_type(CheckType value) {
2978 ASSERT(is_call_stub() || is_keyed_call_stub());
2979 WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
2983 byte Code::unary_op_type() {
2984 ASSERT(is_unary_op_stub());
2985 return READ_BYTE_FIELD(this, kUnaryOpTypeOffset);
2989 void Code::set_unary_op_type(byte value) {
2990 ASSERT(is_unary_op_stub());
2991 WRITE_BYTE_FIELD(this, kUnaryOpTypeOffset, value);
2995 byte Code::binary_op_type() {
2996 ASSERT(is_binary_op_stub());
2997 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
3001 void Code::set_binary_op_type(byte value) {
3002 ASSERT(is_binary_op_stub());
3003 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
3007 byte Code::binary_op_result_type() {
3008 ASSERT(is_binary_op_stub());
3009 return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
3013 void Code::set_binary_op_result_type(byte value) {
3014 ASSERT(is_binary_op_stub());
3015 WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
3019 byte Code::compare_state() {
3020 ASSERT(is_compare_ic_stub());
3021 return READ_BYTE_FIELD(this, kCompareStateOffset);
3025 void Code::set_compare_state(byte value) {
3026 ASSERT(is_compare_ic_stub());
3027 WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
3031 byte Code::to_boolean_state() {
3032 ASSERT(is_to_boolean_ic_stub());
3033 return READ_BYTE_FIELD(this, kToBooleanTypeOffset);
3037 void Code::set_to_boolean_state(byte value) {
3038 ASSERT(is_to_boolean_ic_stub());
3039 WRITE_BYTE_FIELD(this, kToBooleanTypeOffset, value);
3043 bool Code::has_function_cache() {
3044 ASSERT(kind() == STUB);
3045 return READ_BYTE_FIELD(this, kHasFunctionCacheOffset) != 0;
3049 void Code::set_has_function_cache(bool flag) {
3050 ASSERT(kind() == STUB);
3051 WRITE_BYTE_FIELD(this, kHasFunctionCacheOffset, flag);
3055 bool Code::is_inline_cache_stub() {
3056 Kind kind = this->kind();
3057 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
3061 Code::Flags Code::ComputeFlags(Kind kind,
3062 InlineCacheState ic_state,
3063 ExtraICState extra_ic_state,
3066 InlineCacheHolderFlag holder) {
3067 // Extra IC state is only allowed for call IC stubs or for store IC
3069 ASSERT(extra_ic_state == kNoExtraICState ||
3072 kind == KEYED_STORE_IC);
3073 // Compute the bit mask.
3074 int bits = KindField::encode(kind)
3075 | ICStateField::encode(ic_state)
3076 | TypeField::encode(type)
3077 | ExtraICStateField::encode(extra_ic_state)
3078 | (argc << kArgumentsCountShift)
3079 | CacheHolderField::encode(holder);
3080 return static_cast<Flags>(bits);
3084 Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
3086 ExtraICState extra_ic_state,
3087 InlineCacheHolderFlag holder,
3089 return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder);
3093 Code::Kind Code::ExtractKindFromFlags(Flags flags) {
3094 return KindField::decode(flags);
3098 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
3099 return ICStateField::decode(flags);
3103 Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
3104 return ExtraICStateField::decode(flags);
3108 PropertyType Code::ExtractTypeFromFlags(Flags flags) {
3109 return TypeField::decode(flags);
3113 int Code::ExtractArgumentsCountFromFlags(Flags flags) {
3114 return (flags & kArgumentsCountMask) >> kArgumentsCountShift;
3118 InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
3119 return CacheHolderField::decode(flags);
3123 Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
3124 int bits = flags & ~TypeField::kMask;
3125 return static_cast<Flags>(bits);
3129 Code* Code::GetCodeFromTargetAddress(Address address) {
3130 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
3131 // GetCodeFromTargetAddress might be called when marking objects during mark
3132 // sweep. reinterpret_cast is therefore used instead of the more appropriate
3133 // Code::cast. Code::cast does not work when the object's map is
3135 Code* result = reinterpret_cast<Code*>(code);
3140 Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
3142 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
3146 Object* Map::prototype() {
3147 return READ_FIELD(this, kPrototypeOffset);
3151 void Map::set_prototype(Object* value, WriteBarrierMode mode) {
3152 ASSERT(value->IsNull() || value->IsJSReceiver());
3153 WRITE_FIELD(this, kPrototypeOffset, value);
3154 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode);
3158 DescriptorArray* Map::instance_descriptors() {
3159 Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
3160 if (object->IsSmi()) {
3161 return HEAP->empty_descriptor_array();
3163 return DescriptorArray::cast(object);
3168 void Map::init_instance_descriptors() {
3169 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, Smi::FromInt(0));
3173 void Map::clear_instance_descriptors() {
3174 Object* object = READ_FIELD(this,
3175 kInstanceDescriptorsOrBitField3Offset);
3176 if (!object->IsSmi()) {
3179 kInstanceDescriptorsOrBitField3Offset,
3180 Smi::FromInt(DescriptorArray::cast(object)->bit_field3_storage()));
3185 void Map::set_instance_descriptors(DescriptorArray* value,
3186 WriteBarrierMode mode) {
3187 Object* object = READ_FIELD(this,
3188 kInstanceDescriptorsOrBitField3Offset);
3189 Heap* heap = GetHeap();
3190 if (value == heap->empty_descriptor_array()) {
3191 clear_instance_descriptors();
3194 if (object->IsSmi()) {
3195 value->set_bit_field3_storage(Smi::cast(object)->value());
3197 value->set_bit_field3_storage(
3198 DescriptorArray::cast(object)->bit_field3_storage());
3201 ASSERT(!is_shared());
3202 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value);
3203 CONDITIONAL_WRITE_BARRIER(
3204 heap, this, kInstanceDescriptorsOrBitField3Offset, value, mode);
3208 int Map::bit_field3() {
3209 Object* object = READ_FIELD(this,
3210 kInstanceDescriptorsOrBitField3Offset);
3211 if (object->IsSmi()) {
3212 return Smi::cast(object)->value();
3214 return DescriptorArray::cast(object)->bit_field3_storage();
3219 void Map::set_bit_field3(int value) {
3220 ASSERT(Smi::IsValid(value));
3221 Object* object = READ_FIELD(this,
3222 kInstanceDescriptorsOrBitField3Offset);
3223 if (object->IsSmi()) {
3225 kInstanceDescriptorsOrBitField3Offset,
3226 Smi::FromInt(value));
3228 DescriptorArray::cast(object)->set_bit_field3_storage(value);
3233 FixedArray* Map::unchecked_prototype_transitions() {
3234 return reinterpret_cast<FixedArray*>(
3235 READ_FIELD(this, kPrototypeTransitionsOffset));
3239 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
3240 ACCESSORS(Map, prototype_transitions, FixedArray, kPrototypeTransitionsOffset)
3241 ACCESSORS(Map, constructor, Object, kConstructorOffset)
3243 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
3244 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset)
3245 ACCESSORS(JSFunction,
3248 kNextFunctionLinkOffset)
3250 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
3251 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
3252 ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
3254 ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
3256 ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
3257 ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
3258 ACCESSORS(AccessorInfo, data, Object, kDataOffset)
3259 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
3260 ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
3262 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
3263 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
3264 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
3266 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
3267 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
3268 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
3269 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
3270 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
3271 ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
3272 ACCESSORS(InterceptorInfo, is_fallback, Smi, kFallbackOffset)
3274 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
3275 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
3277 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
3278 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
3280 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
3281 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
3282 ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
3283 kPropertyAccessorsOffset)
3284 ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
3285 kPrototypeTemplateOffset)
3286 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
3287 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
3288 kNamedPropertyHandlerOffset)
3289 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
3290 kIndexedPropertyHandlerOffset)
3291 ACCESSORS(FunctionTemplateInfo, instance_template, Object,
3292 kInstanceTemplateOffset)
3293 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
3294 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
3295 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
3296 kInstanceCallHandlerOffset)
3297 ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
3298 kAccessCheckInfoOffset)
3299 ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
3301 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
3302 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
3303 kInternalFieldCountOffset)
3305 ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
3306 ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
3308 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
3310 ACCESSORS(Script, source, Object, kSourceOffset)
3311 ACCESSORS(Script, name, Object, kNameOffset)
3312 ACCESSORS(Script, id, Object, kIdOffset)
3313 ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
3314 ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
3315 ACCESSORS(Script, data, Object, kDataOffset)
3316 ACCESSORS(Script, context_data, Object, kContextOffset)
3317 ACCESSORS(Script, wrapper, Foreign, kWrapperOffset)
3318 ACCESSORS(Script, type, Smi, kTypeOffset)
3319 ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
3320 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
3321 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
3322 ACCESSORS(Script, eval_from_instructions_offset, Smi,
3323 kEvalFrominstructionsOffsetOffset)
3325 #ifdef ENABLE_DEBUGGER_SUPPORT
3326 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
3327 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
3328 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
3329 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
3331 ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
3332 ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
3333 ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
3334 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
3337 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
3338 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
3339 ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
3340 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
3341 kInstanceClassNameOffset)
3342 ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
3343 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
3344 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
3345 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
3346 ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
3347 kThisPropertyAssignmentsOffset)
3349 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
3350 kHiddenPrototypeBit)
3351 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
3352 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
3353 kNeedsAccessCheckBit)
3354 BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
3355 kReadOnlyPrototypeBit)
3356 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
3358 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
3360 BOOL_GETTER(SharedFunctionInfo,
3362 has_only_simple_this_property_assignments,
3363 kHasOnlySimpleThisPropertyAssignments)
3364 BOOL_ACCESSORS(SharedFunctionInfo,
3366 allows_lazy_compilation,
3367 kAllowLazyCompilation)
3368 BOOL_ACCESSORS(SharedFunctionInfo,
3372 BOOL_ACCESSORS(SharedFunctionInfo,
3374 has_duplicate_parameters,
3375 kHasDuplicateParameters)
3378 #if V8_HOST_ARCH_32_BIT
3379 SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
3380 SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
3381 kFormalParameterCountOffset)
3382 SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
3383 kExpectedNofPropertiesOffset)
3384 SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3385 SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
3386 kStartPositionAndTypeOffset)
3387 SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
3388 SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
3389 kFunctionTokenPositionOffset)
3390 SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
3391 kCompilerHintsOffset)
3392 SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
3393 kThisPropertyAssignmentsCountOffset)
3394 SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
3397 #define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
3398 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
3399 int holder::name() { \
3400 int value = READ_INT_FIELD(this, offset); \
3401 ASSERT(kHeapObjectTag == 1); \
3402 ASSERT((value & kHeapObjectTag) == 0); \
3403 return value >> 1; \
3405 void holder::set_##name(int value) { \
3406 ASSERT(kHeapObjectTag == 1); \
3407 ASSERT((value & 0xC0000000) == 0xC0000000 || \
3408 (value & 0xC0000000) == 0x000000000); \
3409 WRITE_INT_FIELD(this, \
3411 (value << 1) & ~kHeapObjectTag); \
3414 #define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
3415 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
3416 INT_ACCESSORS(holder, name, offset)
3419 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
3420 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3421 formal_parameter_count,
3422 kFormalParameterCountOffset)
3424 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3425 expected_nof_properties,
3426 kExpectedNofPropertiesOffset)
3427 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3429 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
3430 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3431 start_position_and_type,
3432 kStartPositionAndTypeOffset)
3434 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3435 function_token_position,
3436 kFunctionTokenPositionOffset)
3437 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3439 kCompilerHintsOffset)
3441 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3442 this_property_assignments_count,
3443 kThisPropertyAssignmentsCountOffset)
3444 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
3448 int SharedFunctionInfo::construction_count() {
3449 return READ_BYTE_FIELD(this, kConstructionCountOffset);
3453 void SharedFunctionInfo::set_construction_count(int value) {
3454 ASSERT(0 <= value && value < 256);
3455 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
3459 BOOL_ACCESSORS(SharedFunctionInfo,
3461 live_objects_may_exist,
3462 kLiveObjectsMayExist)
3465 bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
3466 return initial_map() != HEAP->undefined_value();
3470 BOOL_GETTER(SharedFunctionInfo,
3472 optimization_disabled,
3473 kOptimizationDisabled)
3476 void SharedFunctionInfo::set_optimization_disabled(bool disable) {
3477 set_compiler_hints(BooleanBit::set(compiler_hints(),
3478 kOptimizationDisabled,
3480 // If disabling optimizations we reflect that in the code object so
3481 // it will not be counted as optimizable code.
3482 if ((code()->kind() == Code::FUNCTION) && disable) {
3483 code()->set_optimizable(false);
3488 StrictModeFlag SharedFunctionInfo::strict_mode_flag() {
3489 return BooleanBit::get(compiler_hints(), kStrictModeFunction)
3490 ? kStrictMode : kNonStrictMode;
3494 void SharedFunctionInfo::set_strict_mode_flag(StrictModeFlag strict_mode_flag) {
3495 ASSERT(strict_mode_flag == kStrictMode ||
3496 strict_mode_flag == kNonStrictMode);
3497 bool value = strict_mode_flag == kStrictMode;
3499 BooleanBit::set(compiler_hints(), kStrictModeFunction, value));
3503 BOOL_GETTER(SharedFunctionInfo, compiler_hints, strict_mode,
3504 kStrictModeFunction)
3505 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
3506 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
3507 name_should_print_as_anonymous,
3508 kNameShouldPrintAsAnonymous)
3509 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
3510 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
3512 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
3513 ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
3515 ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
3517 bool Script::HasValidSource() {
3518 Object* src = this->source();
3519 if (!src->IsString()) return true;
3520 String* src_str = String::cast(src);
3521 if (!StringShape(src_str).IsExternal()) return true;
3522 if (src_str->IsAsciiRepresentation()) {
3523 return ExternalAsciiString::cast(src)->resource() != NULL;
3524 } else if (src_str->IsTwoByteRepresentation()) {
3525 return ExternalTwoByteString::cast(src)->resource() != NULL;
3531 void SharedFunctionInfo::DontAdaptArguments() {
3532 ASSERT(code()->kind() == Code::BUILTIN);
3533 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
3537 int SharedFunctionInfo::start_position() {
3538 return start_position_and_type() >> kStartPositionShift;
3542 void SharedFunctionInfo::set_start_position(int start_position) {
3543 set_start_position_and_type((start_position << kStartPositionShift)
3544 | (start_position_and_type() & ~kStartPositionMask));
3548 Code* SharedFunctionInfo::code() {
3549 return Code::cast(READ_FIELD(this, kCodeOffset));
3553 Code* SharedFunctionInfo::unchecked_code() {
3554 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
3558 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
3559 WRITE_FIELD(this, kCodeOffset, value);
3560 CONDITIONAL_WRITE_BARRIER(value->GetHeap(), this, kCodeOffset, value, mode);
3564 SerializedScopeInfo* SharedFunctionInfo::scope_info() {
3565 return reinterpret_cast<SerializedScopeInfo*>(
3566 READ_FIELD(this, kScopeInfoOffset));
3570 void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
3571 WriteBarrierMode mode) {
3572 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
3573 CONDITIONAL_WRITE_BARRIER(GetHeap(),
3576 reinterpret_cast<Object*>(value),
3581 Smi* SharedFunctionInfo::deopt_counter() {
3582 return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset));
3586 void SharedFunctionInfo::set_deopt_counter(Smi* value) {
3587 WRITE_FIELD(this, kDeoptCounterOffset, value);
3591 bool SharedFunctionInfo::is_compiled() {
3593 Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
3597 bool SharedFunctionInfo::IsApiFunction() {
3598 return function_data()->IsFunctionTemplateInfo();
3602 FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3603 ASSERT(IsApiFunction());
3604 return FunctionTemplateInfo::cast(function_data());
3608 bool SharedFunctionInfo::HasBuiltinFunctionId() {
3609 return function_data()->IsSmi();
3613 BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3614 ASSERT(HasBuiltinFunctionId());
3615 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
3619 int SharedFunctionInfo::code_age() {
3620 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3624 void SharedFunctionInfo::set_code_age(int code_age) {
3625 set_compiler_hints(compiler_hints() |
3626 ((code_age & kCodeAgeMask) << kCodeAgeShift));
3630 bool SharedFunctionInfo::has_deoptimization_support() {
3631 Code* code = this->code();
3632 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3636 bool JSFunction::IsBuiltin() {
3637 return context()->global()->IsJSBuiltinsObject();
3641 bool JSFunction::NeedsArgumentsAdaption() {
3642 return shared()->formal_parameter_count() !=
3643 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3647 bool JSFunction::IsOptimized() {
3648 return code()->kind() == Code::OPTIMIZED_FUNCTION;
3652 bool JSFunction::IsOptimizable() {
3653 return code()->kind() == Code::FUNCTION && code()->optimizable();
3657 bool JSFunction::IsMarkedForLazyRecompilation() {
3658 return code() == GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile);
3662 Code* JSFunction::code() {
3663 return Code::cast(unchecked_code());
3667 Code* JSFunction::unchecked_code() {
3668 return reinterpret_cast<Code*>(
3669 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
3673 void JSFunction::set_code(Code* value) {
3674 ASSERT(!HEAP->InNewSpace(value));
3675 Address entry = value->entry();
3676 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
3677 GetHeap()->incremental_marking()->RecordWriteOfCodeEntry(
3679 HeapObject::RawField(this, kCodeEntryOffset),
3684 void JSFunction::ReplaceCode(Code* code) {
3685 bool was_optimized = IsOptimized();
3686 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3690 // Add/remove the function from the list of optimized functions for this
3691 // context based on the state change.
3692 if (!was_optimized && is_optimized) {
3693 context()->global_context()->AddOptimizedFunction(this);
3695 if (was_optimized && !is_optimized) {
3696 context()->global_context()->RemoveOptimizedFunction(this);
3701 Context* JSFunction::context() {
3702 return Context::cast(READ_FIELD(this, kContextOffset));
3706 Object* JSFunction::unchecked_context() {
3707 return READ_FIELD(this, kContextOffset);
3711 SharedFunctionInfo* JSFunction::unchecked_shared() {
3712 return reinterpret_cast<SharedFunctionInfo*>(
3713 READ_FIELD(this, kSharedFunctionInfoOffset));
3717 void JSFunction::set_context(Object* value) {
3718 ASSERT(value->IsUndefined() || value->IsContext());
3719 WRITE_FIELD(this, kContextOffset, value);
3720 WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
3723 ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3724 kPrototypeOrInitialMapOffset)
3727 Map* JSFunction::initial_map() {
3728 return Map::cast(prototype_or_initial_map());
3732 void JSFunction::set_initial_map(Map* value) {
3733 set_prototype_or_initial_map(value);
3737 bool JSFunction::has_initial_map() {
3738 return prototype_or_initial_map()->IsMap();
3742 bool JSFunction::has_instance_prototype() {
3743 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3747 bool JSFunction::has_prototype() {
3748 return map()->has_non_instance_prototype() || has_instance_prototype();
3752 Object* JSFunction::instance_prototype() {
3753 ASSERT(has_instance_prototype());
3754 if (has_initial_map()) return initial_map()->prototype();
3755 // When there is no initial map and the prototype is a JSObject, the
3756 // initial map field is used for the prototype field.
3757 return prototype_or_initial_map();
3761 Object* JSFunction::prototype() {
3762 ASSERT(has_prototype());
3763 // If the function's prototype property has been set to a non-JSObject
3764 // value, that value is stored in the constructor field of the map.
3765 if (map()->has_non_instance_prototype()) return map()->constructor();
3766 return instance_prototype();
3769 bool JSFunction::should_have_prototype() {
3770 return map()->function_with_prototype();
3774 bool JSFunction::is_compiled() {
3775 return code() != GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
3779 FixedArray* JSFunction::literals() {
3780 ASSERT(!shared()->bound());
3781 return literals_or_bindings();
3785 void JSFunction::set_literals(FixedArray* literals) {
3786 ASSERT(!shared()->bound());
3787 set_literals_or_bindings(literals);
3791 FixedArray* JSFunction::function_bindings() {
3792 ASSERT(shared()->bound());
3793 return literals_or_bindings();
3797 void JSFunction::set_function_bindings(FixedArray* bindings) {
3798 ASSERT(shared()->bound());
3799 // Bound function literal may be initialized to the empty fixed array
3800 // before the bindings are set.
3801 ASSERT(bindings == GetHeap()->empty_fixed_array() ||
3802 bindings->map() == GetHeap()->fixed_cow_array_map());
3803 set_literals_or_bindings(bindings);
3807 int JSFunction::NumberOfLiterals() {
3808 ASSERT(!shared()->bound());
3809 return literals()->length();
3813 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
3814 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
3815 return READ_FIELD(this, OffsetOfFunctionWithId(id));
3819 void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
3821 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
3822 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
3823 WRITE_BARRIER(GetHeap(), this, OffsetOfFunctionWithId(id), value);
3827 Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
3828 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
3829 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
3833 void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
3835 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
3836 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
3837 ASSERT(!HEAP->InNewSpace(value));
3841 ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
3842 ACCESSORS(JSProxy, hash, Object, kHashOffset)
3843 ACCESSORS(JSFunctionProxy, call_trap, Object, kCallTrapOffset)
3844 ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
3847 void JSProxy::InitializeBody(int object_size, Object* value) {
3848 ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
3849 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
3850 WRITE_FIELD(this, offset, value);
3855 ACCESSORS(JSSet, table, Object, kTableOffset)
3856 ACCESSORS(JSMap, table, Object, kTableOffset)
3857 ACCESSORS(JSWeakMap, table, Object, kTableOffset)
3858 ACCESSORS(JSWeakMap, next, Object, kNextOffset)
3861 ObjectHashTable* JSWeakMap::unchecked_table() {
3862 return reinterpret_cast<ObjectHashTable*>(READ_FIELD(this, kTableOffset));
3866 Address Foreign::foreign_address() {
3867 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset));
3871 void Foreign::set_foreign_address(Address value) {
3872 WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value));
3876 ACCESSORS(JSValue, value, Object, kValueOffset)
3879 JSValue* JSValue::cast(Object* obj) {
3880 ASSERT(obj->IsJSValue());
3881 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
3882 return reinterpret_cast<JSValue*>(obj);
3886 ACCESSORS(JSMessageObject, type, String, kTypeOffset)
3887 ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
3888 ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
3889 ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
3890 ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
3891 SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
3892 SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
3895 JSMessageObject* JSMessageObject::cast(Object* obj) {
3896 ASSERT(obj->IsJSMessageObject());
3897 ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
3898 return reinterpret_cast<JSMessageObject*>(obj);
3902 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
3903 ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
3904 ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
3905 ACCESSORS(Code, next_code_flushing_candidate,
3906 Object, kNextCodeFlushingCandidateOffset)
3909 byte* Code::instruction_start() {
3910 return FIELD_ADDR(this, kHeaderSize);
3914 byte* Code::instruction_end() {
3915 return instruction_start() + instruction_size();
3919 int Code::body_size() {
3920 return RoundUp(instruction_size(), kObjectAlignment);
3924 FixedArray* Code::unchecked_deoptimization_data() {
3925 return reinterpret_cast<FixedArray*>(
3926 READ_FIELD(this, kDeoptimizationDataOffset));
3930 ByteArray* Code::unchecked_relocation_info() {
3931 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
3935 byte* Code::relocation_start() {
3936 return unchecked_relocation_info()->GetDataStartAddress();
3940 int Code::relocation_size() {
3941 return unchecked_relocation_info()->length();
3945 byte* Code::entry() {
3946 return instruction_start();
3950 bool Code::contains(byte* inner_pointer) {
3951 return (address() <= inner_pointer) && (inner_pointer <= address() + Size());
3955 ACCESSORS(JSArray, length, Object, kLengthOffset)
3958 ACCESSORS(JSRegExp, data, Object, kDataOffset)
3961 JSRegExp::Type JSRegExp::TypeTag() {
3962 Object* data = this->data();
3963 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
3964 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
3965 return static_cast<JSRegExp::Type>(smi->value());
3969 JSRegExp::Type JSRegExp::TypeTagUnchecked() {
3970 Smi* smi = Smi::cast(DataAtUnchecked(kTagIndex));
3971 return static_cast<JSRegExp::Type>(smi->value());
3975 int JSRegExp::CaptureCount() {
3976 switch (TypeTag()) {
3980 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
3988 JSRegExp::Flags JSRegExp::GetFlags() {
3989 ASSERT(this->data()->IsFixedArray());
3990 Object* data = this->data();
3991 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
3992 return Flags(smi->value());
3996 String* JSRegExp::Pattern() {
3997 ASSERT(this->data()->IsFixedArray());
3998 Object* data = this->data();
3999 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
4004 Object* JSRegExp::DataAt(int index) {
4005 ASSERT(TypeTag() != NOT_COMPILED);
4006 return FixedArray::cast(data())->get(index);
4010 Object* JSRegExp::DataAtUnchecked(int index) {
4011 FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4012 int offset = FixedArray::kHeaderSize + index * kPointerSize;
4013 return READ_FIELD(fa, offset);
4017 void JSRegExp::SetDataAt(int index, Object* value) {
4018 ASSERT(TypeTag() != NOT_COMPILED);
4019 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
4020 FixedArray::cast(data())->set(index, value);
4024 void JSRegExp::SetDataAtUnchecked(int index, Object* value, Heap* heap) {
4025 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
4026 FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4027 if (value->IsSmi()) {
4028 fa->set_unchecked(index, Smi::cast(value));
4030 // We only do this during GC, so we don't need to notify the write barrier.
4031 fa->set_unchecked(heap, index, value, SKIP_WRITE_BARRIER);
4036 ElementsKind JSObject::GetElementsKind() {
4037 ElementsKind kind = map()->elements_kind();
4039 FixedArrayBase* fixed_array =
4040 reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset));
4041 Map* map = fixed_array->map();
4042 ASSERT(((kind == FAST_ELEMENTS || kind == FAST_SMI_ONLY_ELEMENTS) &&
4043 (map == GetHeap()->fixed_array_map() ||
4044 map == GetHeap()->fixed_cow_array_map())) ||
4045 (kind == FAST_DOUBLE_ELEMENTS &&
4046 fixed_array->IsFixedDoubleArray()) ||
4047 (kind == DICTIONARY_ELEMENTS &&
4048 fixed_array->IsFixedArray() &&
4049 fixed_array->IsDictionary()) ||
4050 (kind > DICTIONARY_ELEMENTS));
4051 ASSERT((kind != NON_STRICT_ARGUMENTS_ELEMENTS) ||
4052 (elements()->IsFixedArray() && elements()->length() >= 2));
4058 ElementsAccessor* JSObject::GetElementsAccessor() {
4059 return ElementsAccessor::ForKind(GetElementsKind());
4063 bool JSObject::HasFastElements() {
4064 return GetElementsKind() == FAST_ELEMENTS;
4068 bool JSObject::HasFastSmiOnlyElements() {
4069 return GetElementsKind() == FAST_SMI_ONLY_ELEMENTS;
4073 bool JSObject::HasFastTypeElements() {
4074 ElementsKind elements_kind = GetElementsKind();
4075 return elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4076 elements_kind == FAST_ELEMENTS;
4080 bool JSObject::HasFastDoubleElements() {
4081 return GetElementsKind() == FAST_DOUBLE_ELEMENTS;
4085 bool JSObject::HasDictionaryElements() {
4086 return GetElementsKind() == DICTIONARY_ELEMENTS;
4090 bool JSObject::HasNonStrictArgumentsElements() {
4091 return GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS;
4095 bool JSObject::HasExternalArrayElements() {
4096 HeapObject* array = elements();
4097 ASSERT(array != NULL);
4098 return array->IsExternalArray();
4102 #define EXTERNAL_ELEMENTS_CHECK(name, type) \
4103 bool JSObject::HasExternal##name##Elements() { \
4104 HeapObject* array = elements(); \
4105 ASSERT(array != NULL); \
4106 if (!array->IsHeapObject()) \
4108 return array->map()->instance_type() == type; \
4112 EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE)
4113 EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
4114 EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE)
4115 EXTERNAL_ELEMENTS_CHECK(UnsignedShort,
4116 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
4117 EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE)
4118 EXTERNAL_ELEMENTS_CHECK(UnsignedInt,
4119 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
4120 EXTERNAL_ELEMENTS_CHECK(Float,
4121 EXTERNAL_FLOAT_ARRAY_TYPE)
4122 EXTERNAL_ELEMENTS_CHECK(Double,
4123 EXTERNAL_DOUBLE_ARRAY_TYPE)
4124 EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
4127 bool JSObject::HasNamedInterceptor() {
4128 return map()->has_named_interceptor();
4132 bool JSObject::HasIndexedInterceptor() {
4133 return map()->has_indexed_interceptor();
4137 bool JSObject::AllowsSetElementsLength() {
4138 bool result = elements()->IsFixedArray() ||
4139 elements()->IsFixedDoubleArray();
4140 ASSERT(result == !HasExternalArrayElements());
4145 MaybeObject* JSObject::EnsureWritableFastElements() {
4146 ASSERT(HasFastTypeElements());
4147 FixedArray* elems = FixedArray::cast(elements());
4148 Isolate* isolate = GetIsolate();
4149 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
4150 Object* writable_elems;
4151 { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap(
4152 elems, isolate->heap()->fixed_array_map());
4153 if (!maybe_writable_elems->ToObject(&writable_elems)) {
4154 return maybe_writable_elems;
4157 set_elements(FixedArray::cast(writable_elems));
4158 isolate->counters()->cow_arrays_converted()->Increment();
4159 return writable_elems;
4163 StringDictionary* JSObject::property_dictionary() {
4164 ASSERT(!HasFastProperties());
4165 return StringDictionary::cast(properties());
4169 NumberDictionary* JSObject::element_dictionary() {
4170 ASSERT(HasDictionaryElements());
4171 return NumberDictionary::cast(elements());
4175 bool String::IsHashFieldComputed(uint32_t field) {
4176 return (field & kHashNotComputedMask) == 0;
4180 bool String::HasHashCode() {
4181 return IsHashFieldComputed(hash_field());
4185 uint32_t String::Hash() {
4186 // Fast case: has hash code already been computed?
4187 uint32_t field = hash_field();
4188 if (IsHashFieldComputed(field)) return field >> kHashShift;
4189 // Slow case: compute hash code and set it.
4190 return ComputeAndSetHash();
4194 StringHasher::StringHasher(int length)
4196 raw_running_hash_(0),
4198 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
4199 is_first_char_(true),
4203 bool StringHasher::has_trivial_hash() {
4204 return length_ > String::kMaxHashCalcLength;
4208 void StringHasher::AddCharacter(uc32 c) {
4209 // Use the Jenkins one-at-a-time hash function to update the hash
4210 // for the given character.
4211 raw_running_hash_ += c;
4212 raw_running_hash_ += (raw_running_hash_ << 10);
4213 raw_running_hash_ ^= (raw_running_hash_ >> 6);
4214 // Incremental array index computation.
4215 if (is_array_index_) {
4216 if (c < '0' || c > '9') {
4217 is_array_index_ = false;
4220 if (is_first_char_) {
4221 is_first_char_ = false;
4222 if (c == '0' && length_ > 1) {
4223 is_array_index_ = false;
4227 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
4228 is_array_index_ = false;
4230 array_index_ = array_index_ * 10 + d;
4237 void StringHasher::AddCharacterNoIndex(uc32 c) {
4238 ASSERT(!is_array_index());
4239 raw_running_hash_ += c;
4240 raw_running_hash_ += (raw_running_hash_ << 10);
4241 raw_running_hash_ ^= (raw_running_hash_ >> 6);
4245 uint32_t StringHasher::GetHash() {
4246 // Get the calculated raw hash value and do some more bit ops to distribute
4247 // the hash further. Ensure that we never return zero as the hash value.
4248 uint32_t result = raw_running_hash_;
4249 result += (result << 3);
4250 result ^= (result >> 11);
4251 result += (result << 15);
4259 template <typename schar>
4260 uint32_t HashSequentialString(const schar* chars, int length) {
4261 StringHasher hasher(length);
4262 if (!hasher.has_trivial_hash()) {
4264 for (i = 0; hasher.is_array_index() && (i < length); i++) {
4265 hasher.AddCharacter(chars[i]);
4267 for (; i < length; i++) {
4268 hasher.AddCharacterNoIndex(chars[i]);
4271 return hasher.GetHashField();
4275 bool String::AsArrayIndex(uint32_t* index) {
4276 uint32_t field = hash_field();
4277 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
4280 return SlowAsArrayIndex(index);
4284 Object* JSReceiver::GetPrototype() {
4285 return HeapObject::cast(this)->map()->prototype();
4289 bool JSReceiver::HasProperty(String* name) {
4291 return JSProxy::cast(this)->HasPropertyWithHandler(name);
4293 return GetPropertyAttribute(name) != ABSENT;
4297 bool JSReceiver::HasLocalProperty(String* name) {
4299 return JSProxy::cast(this)->HasPropertyWithHandler(name);
4301 return GetLocalPropertyAttribute(name) != ABSENT;
4305 PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) {
4306 return GetPropertyAttributeWithReceiver(this, key);
4309 // TODO(504): this may be useful in other places too where JSGlobalProxy
4311 Object* JSObject::BypassGlobalProxy() {
4312 if (IsJSGlobalProxy()) {
4313 Object* proto = GetPrototype();
4314 if (proto->IsNull()) return GetHeap()->undefined_value();
4315 ASSERT(proto->IsJSGlobalObject());
4322 MaybeObject* JSReceiver::GetIdentityHash(CreationFlag flag) {
4324 ? JSProxy::cast(this)->GetIdentityHash(flag)
4325 : JSObject::cast(this)->GetIdentityHash(flag);
4329 bool JSReceiver::HasElement(uint32_t index) {
4331 return JSProxy::cast(this)->HasElementWithHandler(index);
4333 return JSObject::cast(this)->HasElementWithReceiver(this, index);
4337 bool AccessorInfo::all_can_read() {
4338 return BooleanBit::get(flag(), kAllCanReadBit);
4342 void AccessorInfo::set_all_can_read(bool value) {
4343 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
4347 bool AccessorInfo::all_can_write() {
4348 return BooleanBit::get(flag(), kAllCanWriteBit);
4352 void AccessorInfo::set_all_can_write(bool value) {
4353 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
4357 bool AccessorInfo::prohibits_overwriting() {
4358 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
4362 void AccessorInfo::set_prohibits_overwriting(bool value) {
4363 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
4367 PropertyAttributes AccessorInfo::property_attributes() {
4368 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
4372 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
4373 set_flag(Smi::FromInt(AttributesField::update(flag()->value(), attributes)));
4377 template<typename Shape, typename Key>
4378 void Dictionary<Shape, Key>::SetEntry(int entry,
4381 SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
4385 template<typename Shape, typename Key>
4386 void Dictionary<Shape, Key>::SetEntry(int entry,
4389 PropertyDetails details) {
4390 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
4391 int index = HashTable<Shape, Key>::EntryToIndex(entry);
4392 AssertNoAllocation no_gc;
4393 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
4394 FixedArray::set(index, key, mode);
4395 FixedArray::set(index+1, value, mode);
4396 FixedArray::set(index+2, details.AsSmi());
4400 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
4401 ASSERT(other->IsNumber());
4402 return key == static_cast<uint32_t>(other->Number());
4406 uint32_t NumberDictionaryShape::Hash(uint32_t key) {
4407 return ComputeIntegerHash(key);
4411 uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) {
4412 ASSERT(other->IsNumber());
4413 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()));
4417 MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) {
4418 return Isolate::Current()->heap()->NumberFromUint32(key);
4422 bool StringDictionaryShape::IsMatch(String* key, Object* other) {
4423 // We know that all entries in a hash table had their hash keys created.
4424 // Use that knowledge to have fast failure.
4425 if (key->Hash() != String::cast(other)->Hash()) return false;
4426 return key->Equals(String::cast(other));
4430 uint32_t StringDictionaryShape::Hash(String* key) {
4435 uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
4436 return String::cast(other)->Hash();
4440 MaybeObject* StringDictionaryShape::AsObject(String* key) {
4445 template <int entrysize>
4446 bool ObjectHashTableShape<entrysize>::IsMatch(Object* key, Object* other) {
4447 return key->SameValue(other);
4451 template <int entrysize>
4452 uint32_t ObjectHashTableShape<entrysize>::Hash(Object* key) {
4453 ASSERT(!key->IsUndefined() && !key->IsNull());
4454 MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
4455 return Smi::cast(maybe_hash->ToObjectChecked())->value();
4459 template <int entrysize>
4460 uint32_t ObjectHashTableShape<entrysize>::HashForObject(Object* key,
4462 ASSERT(!other->IsUndefined() && !other->IsNull());
4463 MaybeObject* maybe_hash = other->GetHash(OMIT_CREATION);
4464 return Smi::cast(maybe_hash->ToObjectChecked())->value();
4468 template <int entrysize>
4469 MaybeObject* ObjectHashTableShape<entrysize>::AsObject(Object* key) {
4474 void ObjectHashTable::RemoveEntry(int entry) {
4475 RemoveEntry(entry, GetHeap());
4479 void Map::ClearCodeCache(Heap* heap) {
4480 // No write barrier is needed since empty_fixed_array is not in new space.
4481 // Please note this function is used during marking:
4482 // - MarkCompactCollector::MarkUnmarkedObject
4483 ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array()));
4484 WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array());
4488 void JSArray::EnsureSize(int required_size) {
4489 ASSERT(HasFastTypeElements());
4490 FixedArray* elts = FixedArray::cast(elements());
4491 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
4492 if (elts->length() < required_size) {
4493 // Doubling in size would be overkill, but leave some slack to avoid
4494 // constantly growing.
4495 Expand(required_size + (required_size >> 3));
4496 // It's a performance benefit to keep a frequently used array in new-space.
4497 } else if (!GetHeap()->new_space()->Contains(elts) &&
4498 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
4499 // Expand will allocate a new backing store in new space even if the size
4500 // we asked for isn't larger than what we had before.
4501 Expand(required_size);
4506 void JSArray::set_length(Smi* length) {
4507 // Don't need a write barrier for a Smi.
4508 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
4512 MaybeObject* JSArray::SetContent(FixedArray* storage) {
4513 MaybeObject* maybe_object = EnsureCanContainElements(storage);
4514 if (maybe_object->IsFailure()) return maybe_object;
4515 set_length(Smi::FromInt(storage->length()));
4516 set_elements(storage);
4521 MaybeObject* FixedArray::Copy() {
4522 if (length() == 0) return this;
4523 return GetHeap()->CopyFixedArray(this);
4527 MaybeObject* FixedDoubleArray::Copy() {
4528 if (length() == 0) return this;
4529 return GetHeap()->CopyFixedDoubleArray(this);
4533 Relocatable::Relocatable(Isolate* isolate) {
4534 ASSERT(isolate == Isolate::Current());
4536 prev_ = isolate->relocatable_top();
4537 isolate->set_relocatable_top(this);
4541 Relocatable::~Relocatable() {
4542 ASSERT(isolate_ == Isolate::Current());
4543 ASSERT_EQ(isolate_->relocatable_top(), this);
4544 isolate_->set_relocatable_top(prev_);
4548 int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
4549 return map->instance_size();
4553 void Foreign::ForeignIterateBody(ObjectVisitor* v) {
4554 v->VisitExternalReference(
4555 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
4559 template<typename StaticVisitor>
4560 void Foreign::ForeignIterateBody() {
4561 StaticVisitor::VisitExternalReference(
4562 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
4566 void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
4567 typedef v8::String::ExternalAsciiStringResource Resource;
4568 v->VisitExternalAsciiString(
4569 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4573 template<typename StaticVisitor>
4574 void ExternalAsciiString::ExternalAsciiStringIterateBody() {
4575 typedef v8::String::ExternalAsciiStringResource Resource;
4576 StaticVisitor::VisitExternalAsciiString(
4577 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4581 void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
4582 typedef v8::String::ExternalStringResource Resource;
4583 v->VisitExternalTwoByteString(
4584 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4588 template<typename StaticVisitor>
4589 void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
4590 typedef v8::String::ExternalStringResource Resource;
4591 StaticVisitor::VisitExternalTwoByteString(
4592 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4595 #define SLOT_ADDR(obj, offset) \
4596 reinterpret_cast<Object**>((obj)->address() + offset)
4598 template<int start_offset, int end_offset, int size>
4599 void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
4602 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
4606 template<int start_offset>
4607 void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
4610 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
4616 #undef CAST_ACCESSOR
4617 #undef INT_ACCESSORS
4618 #undef SMI_ACCESSORS
4623 #undef WRITE_BARRIER
4624 #undef CONDITIONAL_WRITE_BARRIER
4625 #undef READ_MEMADDR_FIELD
4626 #undef WRITE_MEMADDR_FIELD
4627 #undef READ_DOUBLE_FIELD
4628 #undef WRITE_DOUBLE_FIELD
4629 #undef READ_INT_FIELD
4630 #undef WRITE_INT_FIELD
4631 #undef READ_SHORT_FIELD
4632 #undef WRITE_SHORT_FIELD
4633 #undef READ_BYTE_FIELD
4634 #undef WRITE_BYTE_FIELD
4637 } } // namespace v8::internal
4639 #endif // V8_OBJECTS_INL_H_