1 // Copyright 2006-2008 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
4 // met:
5 //
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.
15 //
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.
27 //
28 // Review notes:
29 //
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.
33 //
34
35 #ifndef V8_OBJECTS_INL_H_
36 #define V8_OBJECTS_INL_H_
37
38 #include "objects.h"
39 #include "contexts.h"
40 #include "conversions-inl.h"
41 #include "property.h"
42
43 namespace v8 {
44 namespace internal {
45
PropertyDetails(Smi * smi)46 PropertyDetails::PropertyDetails(Smi* smi) {
47 value_ = smi->value();
48 }
49
50
AsSmi()51 Smi* PropertyDetails::AsSmi() {
52 return Smi::FromInt(value_);
53 }
54
55
AsDeleted()56 PropertyDetails PropertyDetails::AsDeleted() {
57 PropertyDetails d(DONT_ENUM, NORMAL);
58 Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
59 return PropertyDetails(smi);
60 }
61
62
63 #define CAST_ACCESSOR(type) \
64 type* type::cast(Object* object) { \
65 ASSERT(object->Is##type()); \
66 return reinterpret_cast<type*>(object); \
67 }
68
69
70 #define INT_ACCESSORS(holder, name, offset) \
71 int holder::name() { return READ_INT_FIELD(this, offset); } \
72 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
73
74
75 #define ACCESSORS(holder, name, type, offset) \
76 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
77 void holder::set_##name(type* value, WriteBarrierMode mode) { \
78 WRITE_FIELD(this, offset, value); \
79 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
80 }
81
82
83
84 #define SMI_ACCESSORS(holder, name, offset) \
85 int holder::name() { \
86 Object* value = READ_FIELD(this, offset); \
87 return Smi::cast(value)->value(); \
88 } \
89 void holder::set_##name(int value) { \
90 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
91 }
92
93
94 #define BOOL_GETTER(holder, field, name, offset) \
95 bool holder::name() { \
96 return BooleanBit::get(field(), offset); \
97 } \
98
99
100 #define BOOL_ACCESSORS(holder, field, name, offset) \
101 bool holder::name() { \
102 return BooleanBit::get(field(), offset); \
103 } \
104 void holder::set_##name(bool value) { \
105 set_##field(BooleanBit::set(field(), offset, value)); \
106 }
107
108
IsInstanceOf(FunctionTemplateInfo * expected)109 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
110 // There is a constraint on the object; check.
111 if (!this->IsJSObject()) return false;
112 // Fetch the constructor function of the object.
113 Object* cons_obj = JSObject::cast(this)->map()->constructor();
114 if (!cons_obj->IsJSFunction()) return false;
115 JSFunction* fun = JSFunction::cast(cons_obj);
116 // Iterate through the chain of inheriting function templates to
117 // see if the required one occurs.
118 for (Object* type = fun->shared()->function_data();
119 type->IsFunctionTemplateInfo();
120 type = FunctionTemplateInfo::cast(type)->parent_template()) {
121 if (type == expected) return true;
122 }
123 // Didn't find the required type in the inheritance chain.
124 return false;
125 }
126
127
IsSmi()128 bool Object::IsSmi() {
129 return HAS_SMI_TAG(this);
130 }
131
132
IsHeapObject()133 bool Object::IsHeapObject() {
134 return Internals::HasHeapObjectTag(this);
135 }
136
137
IsHeapNumber()138 bool Object::IsHeapNumber() {
139 return Object::IsHeapObject()
140 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
141 }
142
143
IsString()144 bool Object::IsString() {
145 return Object::IsHeapObject()
146 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
147 }
148
149
IsSymbol()150 bool Object::IsSymbol() {
151 if (!this->IsHeapObject()) return false;
152 uint32_t type = HeapObject::cast(this)->map()->instance_type();
153 return (type & (kIsNotStringMask | kIsSymbolMask)) ==
154 (kStringTag | kSymbolTag);
155 }
156
157
IsConsString()158 bool Object::IsConsString() {
159 if (!this->IsHeapObject()) return false;
160 uint32_t type = HeapObject::cast(this)->map()->instance_type();
161 return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
162 (kStringTag | kConsStringTag);
163 }
164
165
166 #ifdef DEBUG
167 // These are for cast checks. If you need one of these in release
168 // mode you should consider using a StringShape before moving it out
169 // of the ifdef
170
IsSeqString()171 bool Object::IsSeqString() {
172 if (!IsString()) return false;
173 return StringShape(String::cast(this)).IsSequential();
174 }
175
176
IsSeqAsciiString()177 bool Object::IsSeqAsciiString() {
178 if (!IsString()) return false;
179 return StringShape(String::cast(this)).IsSequential() &&
180 String::cast(this)->IsAsciiRepresentation();
181 }
182
183
IsSeqTwoByteString()184 bool Object::IsSeqTwoByteString() {
185 if (!IsString()) return false;
186 return StringShape(String::cast(this)).IsSequential() &&
187 String::cast(this)->IsTwoByteRepresentation();
188 }
189
190
IsExternalString()191 bool Object::IsExternalString() {
192 if (!IsString()) return false;
193 return StringShape(String::cast(this)).IsExternal();
194 }
195
196
IsExternalAsciiString()197 bool Object::IsExternalAsciiString() {
198 if (!IsString()) return false;
199 return StringShape(String::cast(this)).IsExternal() &&
200 String::cast(this)->IsAsciiRepresentation();
201 }
202
203
IsExternalTwoByteString()204 bool Object::IsExternalTwoByteString() {
205 if (!IsString()) return false;
206 return StringShape(String::cast(this)).IsExternal() &&
207 String::cast(this)->IsTwoByteRepresentation();
208 }
209
210
IsSlicedString()211 bool Object::IsSlicedString() {
212 if (!IsString()) return false;
213 return StringShape(String::cast(this)).IsSliced();
214 }
215
216
217 #endif // DEBUG
218
219
StringShape(String * str)220 StringShape::StringShape(String* str)
221 : type_(str->map()->instance_type()) {
222 set_valid();
223 ASSERT((type_ & kIsNotStringMask) == kStringTag);
224 }
225
226
StringShape(Map * map)227 StringShape::StringShape(Map* map)
228 : type_(map->instance_type()) {
229 set_valid();
230 ASSERT((type_ & kIsNotStringMask) == kStringTag);
231 }
232
233
StringShape(InstanceType t)234 StringShape::StringShape(InstanceType t)
235 : type_(static_cast<uint32_t>(t)) {
236 set_valid();
237 ASSERT((type_ & kIsNotStringMask) == kStringTag);
238 }
239
240
IsSymbol()241 bool StringShape::IsSymbol() {
242 ASSERT(valid());
243 return (type_ & kIsSymbolMask) == kSymbolTag;
244 }
245
246
IsAsciiRepresentation()247 bool String::IsAsciiRepresentation() {
248 uint32_t type = map()->instance_type();
249 if ((type & kStringRepresentationMask) == kSlicedStringTag) {
250 return SlicedString::cast(this)->buffer()->IsAsciiRepresentation();
251 }
252 if ((type & kStringRepresentationMask) == kConsStringTag &&
253 ConsString::cast(this)->second()->length() == 0) {
254 return ConsString::cast(this)->first()->IsAsciiRepresentation();
255 }
256 return (type & kStringEncodingMask) == kAsciiStringTag;
257 }
258
259
IsTwoByteRepresentation()260 bool String::IsTwoByteRepresentation() {
261 uint32_t type = map()->instance_type();
262 if ((type & kStringRepresentationMask) == kSlicedStringTag) {
263 return SlicedString::cast(this)->buffer()->IsTwoByteRepresentation();
264 } else if ((type & kStringRepresentationMask) == kConsStringTag &&
265 ConsString::cast(this)->second()->length() == 0) {
266 return ConsString::cast(this)->first()->IsTwoByteRepresentation();
267 }
268 return (type & kStringEncodingMask) == kTwoByteStringTag;
269 }
270
271
IsCons()272 bool StringShape::IsCons() {
273 return (type_ & kStringRepresentationMask) == kConsStringTag;
274 }
275
276
IsSliced()277 bool StringShape::IsSliced() {
278 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
279 }
280
281
IsExternal()282 bool StringShape::IsExternal() {
283 return (type_ & kStringRepresentationMask) == kExternalStringTag;
284 }
285
286
IsSequential()287 bool StringShape::IsSequential() {
288 return (type_ & kStringRepresentationMask) == kSeqStringTag;
289 }
290
291
representation_tag()292 StringRepresentationTag StringShape::representation_tag() {
293 uint32_t tag = (type_ & kStringRepresentationMask);
294 return static_cast<StringRepresentationTag>(tag);
295 }
296
297
full_representation_tag()298 uint32_t StringShape::full_representation_tag() {
299 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
300 }
301
302
303 STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
304 Internals::kFullStringRepresentationMask);
305
306
size_tag()307 uint32_t StringShape::size_tag() {
308 return (type_ & kStringSizeMask);
309 }
310
311
IsSequentialAscii()312 bool StringShape::IsSequentialAscii() {
313 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
314 }
315
316
IsSequentialTwoByte()317 bool StringShape::IsSequentialTwoByte() {
318 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
319 }
320
321
IsExternalAscii()322 bool StringShape::IsExternalAscii() {
323 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
324 }
325
326
IsExternalTwoByte()327 bool StringShape::IsExternalTwoByte() {
328 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
329 }
330
331
332 STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
333 Internals::kExternalTwoByteRepresentationTag);
334
335
Get(int index)336 uc32 FlatStringReader::Get(int index) {
337 ASSERT(0 <= index && index <= length_);
338 if (is_ascii_) {
339 return static_cast<const byte*>(start_)[index];
340 } else {
341 return static_cast<const uc16*>(start_)[index];
342 }
343 }
344
345
IsNumber()346 bool Object::IsNumber() {
347 return IsSmi() || IsHeapNumber();
348 }
349
350
IsByteArray()351 bool Object::IsByteArray() {
352 return Object::IsHeapObject()
353 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
354 }
355
356
IsPixelArray()357 bool Object::IsPixelArray() {
358 return Object::IsHeapObject() &&
359 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
360 }
361
362
IsFailure()363 bool Object::IsFailure() {
364 return HAS_FAILURE_TAG(this);
365 }
366
367
IsRetryAfterGC()368 bool Object::IsRetryAfterGC() {
369 return HAS_FAILURE_TAG(this)
370 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
371 }
372
373
IsOutOfMemoryFailure()374 bool Object::IsOutOfMemoryFailure() {
375 return HAS_FAILURE_TAG(this)
376 && Failure::cast(this)->IsOutOfMemoryException();
377 }
378
379
IsException()380 bool Object::IsException() {
381 return this == Failure::Exception();
382 }
383
384
IsJSObject()385 bool Object::IsJSObject() {
386 return IsHeapObject()
387 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
388 }
389
390
IsJSContextExtensionObject()391 bool Object::IsJSContextExtensionObject() {
392 return IsHeapObject()
393 && (HeapObject::cast(this)->map()->instance_type() ==
394 JS_CONTEXT_EXTENSION_OBJECT_TYPE);
395 }
396
397
IsMap()398 bool Object::IsMap() {
399 return Object::IsHeapObject()
400 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
401 }
402
403
IsFixedArray()404 bool Object::IsFixedArray() {
405 return Object::IsHeapObject()
406 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
407 }
408
409
IsDescriptorArray()410 bool Object::IsDescriptorArray() {
411 return IsFixedArray();
412 }
413
414
IsContext()415 bool Object::IsContext() {
416 return Object::IsHeapObject()
417 && (HeapObject::cast(this)->map() == Heap::context_map() ||
418 HeapObject::cast(this)->map() == Heap::catch_context_map() ||
419 HeapObject::cast(this)->map() == Heap::global_context_map());
420 }
421
422
IsCatchContext()423 bool Object::IsCatchContext() {
424 return Object::IsHeapObject()
425 && HeapObject::cast(this)->map() == Heap::catch_context_map();
426 }
427
428
IsGlobalContext()429 bool Object::IsGlobalContext() {
430 return Object::IsHeapObject()
431 && HeapObject::cast(this)->map() == Heap::global_context_map();
432 }
433
434
IsJSFunction()435 bool Object::IsJSFunction() {
436 return Object::IsHeapObject()
437 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
438 }
439
440
441 template <> inline bool Is<JSFunction>(Object* obj) {
442 return obj->IsJSFunction();
443 }
444
445
IsCode()446 bool Object::IsCode() {
447 return Object::IsHeapObject()
448 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
449 }
450
451
IsOddball()452 bool Object::IsOddball() {
453 return Object::IsHeapObject()
454 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
455 }
456
457
IsJSGlobalPropertyCell()458 bool Object::IsJSGlobalPropertyCell() {
459 return Object::IsHeapObject()
460 && HeapObject::cast(this)->map()->instance_type()
461 == JS_GLOBAL_PROPERTY_CELL_TYPE;
462 }
463
464
IsSharedFunctionInfo()465 bool Object::IsSharedFunctionInfo() {
466 return Object::IsHeapObject() &&
467 (HeapObject::cast(this)->map()->instance_type() ==
468 SHARED_FUNCTION_INFO_TYPE);
469 }
470
471
IsJSValue()472 bool Object::IsJSValue() {
473 return Object::IsHeapObject()
474 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
475 }
476
477
IsStringWrapper()478 bool Object::IsStringWrapper() {
479 return IsJSValue() && JSValue::cast(this)->value()->IsString();
480 }
481
482
IsProxy()483 bool Object::IsProxy() {
484 return Object::IsHeapObject()
485 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
486 }
487
488
IsBoolean()489 bool Object::IsBoolean() {
490 return IsTrue() || IsFalse();
491 }
492
493
IsJSArray()494 bool Object::IsJSArray() {
495 return Object::IsHeapObject()
496 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
497 }
498
499
IsJSRegExp()500 bool Object::IsJSRegExp() {
501 return Object::IsHeapObject()
502 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
503 }
504
505
506 template <> inline bool Is<JSArray>(Object* obj) {
507 return obj->IsJSArray();
508 }
509
510
IsHashTable()511 bool Object::IsHashTable() {
512 return Object::IsHeapObject()
513 && HeapObject::cast(this)->map() == Heap::hash_table_map();
514 }
515
516
IsDictionary()517 bool Object::IsDictionary() {
518 return IsHashTable() && this != Heap::symbol_table();
519 }
520
521
IsSymbolTable()522 bool Object::IsSymbolTable() {
523 return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
524 }
525
526
IsCompilationCacheTable()527 bool Object::IsCompilationCacheTable() {
528 return IsHashTable();
529 }
530
531
IsMapCache()532 bool Object::IsMapCache() {
533 return IsHashTable();
534 }
535
536
IsPrimitive()537 bool Object::IsPrimitive() {
538 return IsOddball() || IsNumber() || IsString();
539 }
540
541
IsJSGlobalProxy()542 bool Object::IsJSGlobalProxy() {
543 bool result = IsHeapObject() &&
544 (HeapObject::cast(this)->map()->instance_type() ==
545 JS_GLOBAL_PROXY_TYPE);
546 ASSERT(!result || IsAccessCheckNeeded());
547 return result;
548 }
549
550
IsGlobalObject()551 bool Object::IsGlobalObject() {
552 if (!IsHeapObject()) return false;
553
554 InstanceType type = HeapObject::cast(this)->map()->instance_type();
555 return type == JS_GLOBAL_OBJECT_TYPE ||
556 type == JS_BUILTINS_OBJECT_TYPE;
557 }
558
559
IsJSGlobalObject()560 bool Object::IsJSGlobalObject() {
561 return IsHeapObject() &&
562 (HeapObject::cast(this)->map()->instance_type() ==
563 JS_GLOBAL_OBJECT_TYPE);
564 }
565
566
IsJSBuiltinsObject()567 bool Object::IsJSBuiltinsObject() {
568 return IsHeapObject() &&
569 (HeapObject::cast(this)->map()->instance_type() ==
570 JS_BUILTINS_OBJECT_TYPE);
571 }
572
573
IsUndetectableObject()574 bool Object::IsUndetectableObject() {
575 return IsHeapObject()
576 && HeapObject::cast(this)->map()->is_undetectable();
577 }
578
579
IsAccessCheckNeeded()580 bool Object::IsAccessCheckNeeded() {
581 return IsHeapObject()
582 && HeapObject::cast(this)->map()->is_access_check_needed();
583 }
584
585
IsStruct()586 bool Object::IsStruct() {
587 if (!IsHeapObject()) return false;
588 switch (HeapObject::cast(this)->map()->instance_type()) {
589 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
590 STRUCT_LIST(MAKE_STRUCT_CASE)
591 #undef MAKE_STRUCT_CASE
592 default: return false;
593 }
594 }
595
596
597 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
598 bool Object::Is##Name() { \
599 return Object::IsHeapObject() \
600 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
601 }
STRUCT_LIST(MAKE_STRUCT_PREDICATE)602 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
603 #undef MAKE_STRUCT_PREDICATE
604
605
606 bool Object::IsUndefined() {
607 return this == Heap::undefined_value();
608 }
609
610
IsTheHole()611 bool Object::IsTheHole() {
612 return this == Heap::the_hole_value();
613 }
614
615
IsNull()616 bool Object::IsNull() {
617 return this == Heap::null_value();
618 }
619
620
IsTrue()621 bool Object::IsTrue() {
622 return this == Heap::true_value();
623 }
624
625
IsFalse()626 bool Object::IsFalse() {
627 return this == Heap::false_value();
628 }
629
630
Number()631 double Object::Number() {
632 ASSERT(IsNumber());
633 return IsSmi()
634 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
635 : reinterpret_cast<HeapNumber*>(this)->value();
636 }
637
638
639
ToSmi()640 Object* Object::ToSmi() {
641 if (IsSmi()) return this;
642 if (IsHeapNumber()) {
643 double value = HeapNumber::cast(this)->value();
644 int int_value = FastD2I(value);
645 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
646 return Smi::FromInt(int_value);
647 }
648 }
649 return Failure::Exception();
650 }
651
652
HasSpecificClassOf(String * name)653 bool Object::HasSpecificClassOf(String* name) {
654 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
655 }
656
657
GetElement(uint32_t index)658 Object* Object::GetElement(uint32_t index) {
659 return GetElementWithReceiver(this, index);
660 }
661
662
GetProperty(String * key)663 Object* Object::GetProperty(String* key) {
664 PropertyAttributes attributes;
665 return GetPropertyWithReceiver(this, key, &attributes);
666 }
667
668
GetProperty(String * key,PropertyAttributes * attributes)669 Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
670 return GetPropertyWithReceiver(this, key, attributes);
671 }
672
673
674 #define FIELD_ADDR(p, offset) \
675 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
676
677 #define READ_FIELD(p, offset) \
678 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
679
680 #define WRITE_FIELD(p, offset, value) \
681 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
682
683
684 #define WRITE_BARRIER(object, offset) \
685 Heap::RecordWrite(object->address(), offset);
686
687 // CONDITIONAL_WRITE_BARRIER must be issued after the actual
688 // write due to the assert validating the written value.
689 #define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
690 if (mode == UPDATE_WRITE_BARRIER) { \
691 Heap::RecordWrite(object->address(), offset); \
692 } else { \
693 ASSERT(mode == SKIP_WRITE_BARRIER); \
694 ASSERT(Heap::InNewSpace(object) || \
695 !Heap::InNewSpace(READ_FIELD(object, offset))); \
696 }
697
698 #define READ_DOUBLE_FIELD(p, offset) \
699 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
700
701 #define WRITE_DOUBLE_FIELD(p, offset, value) \
702 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
703
704 #define READ_INT_FIELD(p, offset) \
705 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
706
707 #define WRITE_INT_FIELD(p, offset, value) \
708 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
709
710 #define READ_INTPTR_FIELD(p, offset) \
711 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
712
713 #define WRITE_INTPTR_FIELD(p, offset, value) \
714 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
715
716 #define READ_UINT32_FIELD(p, offset) \
717 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
718
719 #define WRITE_UINT32_FIELD(p, offset, value) \
720 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
721
722 #define READ_SHORT_FIELD(p, offset) \
723 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
724
725 #define WRITE_SHORT_FIELD(p, offset, value) \
726 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
727
728 #define READ_BYTE_FIELD(p, offset) \
729 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
730
731 #define WRITE_BYTE_FIELD(p, offset, value) \
732 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
733
734
RawField(HeapObject * obj,int byte_offset)735 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
736 return &READ_FIELD(obj, byte_offset);
737 }
738
739
value()740 int Smi::value() {
741 return Internals::SmiValue(this);
742 }
743
744
FromInt(int value)745 Smi* Smi::FromInt(int value) {
746 ASSERT(Smi::IsValid(value));
747 intptr_t tagged_value =
748 (static_cast<intptr_t>(value) << kSmiTagSize) | kSmiTag;
749 return reinterpret_cast<Smi*>(tagged_value);
750 }
751
752
FromIntptr(intptr_t value)753 Smi* Smi::FromIntptr(intptr_t value) {
754 ASSERT(Smi::IsValid(value));
755 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
756 }
757
758
type()759 Failure::Type Failure::type() const {
760 return static_cast<Type>(value() & kFailureTypeTagMask);
761 }
762
763
IsInternalError()764 bool Failure::IsInternalError() const {
765 return type() == INTERNAL_ERROR;
766 }
767
768
IsOutOfMemoryException()769 bool Failure::IsOutOfMemoryException() const {
770 return type() == OUT_OF_MEMORY_EXCEPTION;
771 }
772
773
requested()774 int Failure::requested() const {
775 const int kShiftBits =
776 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
777 STATIC_ASSERT(kShiftBits >= 0);
778 ASSERT(type() == RETRY_AFTER_GC);
779 return value() >> kShiftBits;
780 }
781
782
allocation_space()783 AllocationSpace Failure::allocation_space() const {
784 ASSERT_EQ(RETRY_AFTER_GC, type());
785 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
786 & kSpaceTagMask);
787 }
788
789
InternalError()790 Failure* Failure::InternalError() {
791 return Construct(INTERNAL_ERROR);
792 }
793
794
Exception()795 Failure* Failure::Exception() {
796 return Construct(EXCEPTION);
797 }
798
799
OutOfMemoryException()800 Failure* Failure::OutOfMemoryException() {
801 return Construct(OUT_OF_MEMORY_EXCEPTION);
802 }
803
804
value()805 int Failure::value() const {
806 return static_cast<int>(reinterpret_cast<intptr_t>(this) >> kFailureTagSize);
807 }
808
809
RetryAfterGC(int requested_bytes)810 Failure* Failure::RetryAfterGC(int requested_bytes) {
811 // Assert that the space encoding fits in the three bytes allotted for it.
812 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
813 int requested = requested_bytes >> kObjectAlignmentBits;
814 int value = (requested << kSpaceTagSize) | NEW_SPACE;
815 ASSERT(value >> kSpaceTagSize == requested);
816 ASSERT(Smi::IsValid(value));
817 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
818 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
819 return Construct(RETRY_AFTER_GC, value);
820 }
821
822
Construct(Type type,int value)823 Failure* Failure::Construct(Type type, int value) {
824 int info = (value << kFailureTypeTagSize) | type;
825 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
826 return reinterpret_cast<Failure*>(
827 (static_cast<intptr_t>(info) << kFailureTagSize) | kFailureTag);
828 }
829
830
IsValid(intptr_t value)831 bool Smi::IsValid(intptr_t value) {
832 #ifdef DEBUG
833 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
834 #endif
835 // To be representable as an tagged small integer, the two
836 // most-significant bits of 'value' must be either 00 or 11 due to
837 // sign-extension. To check this we add 01 to the two
838 // most-significant bits, and check if the most-significant bit is 0
839 //
840 // CAUTION: The original code below:
841 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
842 // may lead to incorrect results according to the C language spec, and
843 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
844 // compiler may produce undefined results in case of signed integer
845 // overflow. The computation must be done w/ unsigned ints.
846 bool result =
847 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
848 ASSERT(result == in_range);
849 return result;
850 }
851
852
IsIntptrValid(intptr_t value)853 bool Smi::IsIntptrValid(intptr_t value) {
854 #ifdef DEBUG
855 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
856 #endif
857 // See Smi::IsValid(int) for description.
858 bool result =
859 ((static_cast<uintptr_t>(value) + 0x40000000U) < 0x80000000U);
860 ASSERT(result == in_range);
861 return result;
862 }
863
864
FromMap(Map * map)865 MapWord MapWord::FromMap(Map* map) {
866 return MapWord(reinterpret_cast<uintptr_t>(map));
867 }
868
869
ToMap()870 Map* MapWord::ToMap() {
871 return reinterpret_cast<Map*>(value_);
872 }
873
874
IsForwardingAddress()875 bool MapWord::IsForwardingAddress() {
876 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
877 }
878
879
FromForwardingAddress(HeapObject * object)880 MapWord MapWord::FromForwardingAddress(HeapObject* object) {
881 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
882 return MapWord(reinterpret_cast<uintptr_t>(raw));
883 }
884
885
ToForwardingAddress()886 HeapObject* MapWord::ToForwardingAddress() {
887 ASSERT(IsForwardingAddress());
888 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
889 }
890
891
IsMarked()892 bool MapWord::IsMarked() {
893 return (value_ & kMarkingMask) == 0;
894 }
895
896
SetMark()897 void MapWord::SetMark() {
898 value_ &= ~kMarkingMask;
899 }
900
901
ClearMark()902 void MapWord::ClearMark() {
903 value_ |= kMarkingMask;
904 }
905
906
IsOverflowed()907 bool MapWord::IsOverflowed() {
908 return (value_ & kOverflowMask) != 0;
909 }
910
911
SetOverflow()912 void MapWord::SetOverflow() {
913 value_ |= kOverflowMask;
914 }
915
916
ClearOverflow()917 void MapWord::ClearOverflow() {
918 value_ &= ~kOverflowMask;
919 }
920
921
EncodeAddress(Address map_address,int offset)922 MapWord MapWord::EncodeAddress(Address map_address, int offset) {
923 // Offset is the distance in live bytes from the first live object in the
924 // same page. The offset between two objects in the same page should not
925 // exceed the object area size of a page.
926 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
927
928 int compact_offset = offset >> kObjectAlignmentBits;
929 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
930
931 Page* map_page = Page::FromAddress(map_address);
932 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
933
934 int map_page_offset =
935 map_page->Offset(map_address) >> kObjectAlignmentBits;
936
937 uintptr_t encoding =
938 (compact_offset << kForwardingOffsetShift) |
939 (map_page_offset << kMapPageOffsetShift) |
940 (map_page->mc_page_index << kMapPageIndexShift);
941 return MapWord(encoding);
942 }
943
944
DecodeMapAddress(MapSpace * map_space)945 Address MapWord::DecodeMapAddress(MapSpace* map_space) {
946 int map_page_index =
947 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
948 ASSERT_MAP_PAGE_INDEX(map_page_index);
949
950 int map_page_offset = static_cast<int>(
951 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
952 << kObjectAlignmentBits);
953
954 return (map_space->PageAddress(map_page_index) + map_page_offset);
955 }
956
957
DecodeOffset()958 int MapWord::DecodeOffset() {
959 // The offset field is represented in the kForwardingOffsetBits
960 // most-significant bits.
961 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
962 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
963 return offset;
964 }
965
966
FromEncodedAddress(Address address)967 MapWord MapWord::FromEncodedAddress(Address address) {
968 return MapWord(reinterpret_cast<uintptr_t>(address));
969 }
970
971
ToEncodedAddress()972 Address MapWord::ToEncodedAddress() {
973 return reinterpret_cast<Address>(value_);
974 }
975
976
977 #ifdef DEBUG
VerifyObjectField(int offset)978 void HeapObject::VerifyObjectField(int offset) {
979 VerifyPointer(READ_FIELD(this, offset));
980 }
981 #endif
982
983
map()984 Map* HeapObject::map() {
985 return map_word().ToMap();
986 }
987
988
set_map(Map * value)989 void HeapObject::set_map(Map* value) {
990 set_map_word(MapWord::FromMap(value));
991 }
992
993
map_word()994 MapWord HeapObject::map_word() {
995 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
996 }
997
998
set_map_word(MapWord map_word)999 void HeapObject::set_map_word(MapWord map_word) {
1000 // WRITE_FIELD does not update the remembered set, but there is no need
1001 // here.
1002 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1003 }
1004
1005
FromAddress(Address address)1006 HeapObject* HeapObject::FromAddress(Address address) {
1007 ASSERT_TAG_ALIGNED(address);
1008 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1009 }
1010
1011
address()1012 Address HeapObject::address() {
1013 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1014 }
1015
1016
Size()1017 int HeapObject::Size() {
1018 return SizeFromMap(map());
1019 }
1020
1021
IteratePointers(ObjectVisitor * v,int start,int end)1022 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1023 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1024 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1025 }
1026
1027
IteratePointer(ObjectVisitor * v,int offset)1028 void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1029 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1030 }
1031
1032
IsMarked()1033 bool HeapObject::IsMarked() {
1034 return map_word().IsMarked();
1035 }
1036
1037
SetMark()1038 void HeapObject::SetMark() {
1039 ASSERT(!IsMarked());
1040 MapWord first_word = map_word();
1041 first_word.SetMark();
1042 set_map_word(first_word);
1043 }
1044
1045
ClearMark()1046 void HeapObject::ClearMark() {
1047 ASSERT(IsMarked());
1048 MapWord first_word = map_word();
1049 first_word.ClearMark();
1050 set_map_word(first_word);
1051 }
1052
1053
IsOverflowed()1054 bool HeapObject::IsOverflowed() {
1055 return map_word().IsOverflowed();
1056 }
1057
1058
SetOverflow()1059 void HeapObject::SetOverflow() {
1060 MapWord first_word = map_word();
1061 first_word.SetOverflow();
1062 set_map_word(first_word);
1063 }
1064
1065
ClearOverflow()1066 void HeapObject::ClearOverflow() {
1067 ASSERT(IsOverflowed());
1068 MapWord first_word = map_word();
1069 first_word.ClearOverflow();
1070 set_map_word(first_word);
1071 }
1072
1073
value()1074 double HeapNumber::value() {
1075 return READ_DOUBLE_FIELD(this, kValueOffset);
1076 }
1077
1078
set_value(double value)1079 void HeapNumber::set_value(double value) {
1080 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1081 }
1082
1083
ACCESSORS(JSObject,properties,FixedArray,kPropertiesOffset)1084 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1085
1086
1087 Array* JSObject::elements() {
1088 Object* array = READ_FIELD(this, kElementsOffset);
1089 // In the assert below Dictionary is covered under FixedArray.
1090 ASSERT(array->IsFixedArray() || array->IsPixelArray());
1091 return reinterpret_cast<Array*>(array);
1092 }
1093
1094
set_elements(Array * value,WriteBarrierMode mode)1095 void JSObject::set_elements(Array* value, WriteBarrierMode mode) {
1096 // In the assert below Dictionary is covered under FixedArray.
1097 ASSERT(value->IsFixedArray() || value->IsPixelArray());
1098 WRITE_FIELD(this, kElementsOffset, value);
1099 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1100 }
1101
1102
initialize_properties()1103 void JSObject::initialize_properties() {
1104 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1105 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1106 }
1107
1108
initialize_elements()1109 void JSObject::initialize_elements() {
1110 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1111 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1112 }
1113
1114
ACCESSORS(Oddball,to_string,String,kToStringOffset)1115 ACCESSORS(Oddball, to_string, String, kToStringOffset)
1116 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1117
1118
1119 Object* JSGlobalPropertyCell::value() {
1120 return READ_FIELD(this, kValueOffset);
1121 }
1122
1123
set_value(Object * val,WriteBarrierMode ignored)1124 void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1125 // The write barrier is not used for global property cells.
1126 ASSERT(!val->IsJSGlobalPropertyCell());
1127 WRITE_FIELD(this, kValueOffset, val);
1128 }
1129
1130
GetHeaderSize()1131 int JSObject::GetHeaderSize() {
1132 InstanceType type = map()->instance_type();
1133 // Check for the most common kind of JavaScript object before
1134 // falling into the generic switch. This speeds up the internal
1135 // field operations considerably on average.
1136 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1137 switch (type) {
1138 case JS_GLOBAL_PROXY_TYPE:
1139 return JSGlobalProxy::kSize;
1140 case JS_GLOBAL_OBJECT_TYPE:
1141 return JSGlobalObject::kSize;
1142 case JS_BUILTINS_OBJECT_TYPE:
1143 return JSBuiltinsObject::kSize;
1144 case JS_FUNCTION_TYPE:
1145 return JSFunction::kSize;
1146 case JS_VALUE_TYPE:
1147 return JSValue::kSize;
1148 case JS_ARRAY_TYPE:
1149 return JSValue::kSize;
1150 case JS_REGEXP_TYPE:
1151 return JSValue::kSize;
1152 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1153 return JSObject::kHeaderSize;
1154 default:
1155 UNREACHABLE();
1156 return 0;
1157 }
1158 }
1159
1160
GetInternalFieldCount()1161 int JSObject::GetInternalFieldCount() {
1162 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1163 // Make sure to adjust for the number of in-object properties. These
1164 // properties do contribute to the size, but are not internal fields.
1165 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1166 map()->inobject_properties();
1167 }
1168
1169
GetInternalField(int index)1170 Object* JSObject::GetInternalField(int index) {
1171 ASSERT(index < GetInternalFieldCount() && index >= 0);
1172 // Internal objects do follow immediately after the header, whereas in-object
1173 // properties are at the end of the object. Therefore there is no need
1174 // to adjust the index here.
1175 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1176 }
1177
1178
SetInternalField(int index,Object * value)1179 void JSObject::SetInternalField(int index, Object* value) {
1180 ASSERT(index < GetInternalFieldCount() && index >= 0);
1181 // Internal objects do follow immediately after the header, whereas in-object
1182 // properties are at the end of the object. Therefore there is no need
1183 // to adjust the index here.
1184 int offset = GetHeaderSize() + (kPointerSize * index);
1185 WRITE_FIELD(this, offset, value);
1186 WRITE_BARRIER(this, offset);
1187 }
1188
1189
1190 // Access fast-case object properties at index. The use of these routines
1191 // is needed to correctly distinguish between properties stored in-object and
1192 // properties stored in the properties array.
FastPropertyAt(int index)1193 Object* JSObject::FastPropertyAt(int index) {
1194 // Adjust for the number of properties stored in the object.
1195 index -= map()->inobject_properties();
1196 if (index < 0) {
1197 int offset = map()->instance_size() + (index * kPointerSize);
1198 return READ_FIELD(this, offset);
1199 } else {
1200 ASSERT(index < properties()->length());
1201 return properties()->get(index);
1202 }
1203 }
1204
1205
FastPropertyAtPut(int index,Object * value)1206 Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1207 // Adjust for the number of properties stored in the object.
1208 index -= map()->inobject_properties();
1209 if (index < 0) {
1210 int offset = map()->instance_size() + (index * kPointerSize);
1211 WRITE_FIELD(this, offset, value);
1212 WRITE_BARRIER(this, offset);
1213 } else {
1214 ASSERT(index < properties()->length());
1215 properties()->set(index, value);
1216 }
1217 return value;
1218 }
1219
1220
InObjectPropertyAt(int index)1221 Object* JSObject::InObjectPropertyAt(int index) {
1222 // Adjust for the number of properties stored in the object.
1223 index -= map()->inobject_properties();
1224 ASSERT(index < 0);
1225 int offset = map()->instance_size() + (index * kPointerSize);
1226 return READ_FIELD(this, offset);
1227 }
1228
1229
InObjectPropertyAtPut(int index,Object * value,WriteBarrierMode mode)1230 Object* JSObject::InObjectPropertyAtPut(int index,
1231 Object* value,
1232 WriteBarrierMode mode) {
1233 // Adjust for the number of properties stored in the object.
1234 index -= map()->inobject_properties();
1235 ASSERT(index < 0);
1236 int offset = map()->instance_size() + (index * kPointerSize);
1237 WRITE_FIELD(this, offset, value);
1238 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1239 return value;
1240 }
1241
1242
1243
InitializeBody(int object_size)1244 void JSObject::InitializeBody(int object_size) {
1245 Object* value = Heap::undefined_value();
1246 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1247 WRITE_FIELD(this, offset, value);
1248 }
1249 }
1250
1251
InitializeBody(int object_size)1252 void Struct::InitializeBody(int object_size) {
1253 Object* value = Heap::undefined_value();
1254 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1255 WRITE_FIELD(this, offset, value);
1256 }
1257 }
1258
1259
HasFastProperties()1260 bool JSObject::HasFastProperties() {
1261 return !properties()->IsDictionary();
1262 }
1263
1264
IndexFromObject(Object * object,uint32_t * index)1265 bool Array::IndexFromObject(Object* object, uint32_t* index) {
1266 if (object->IsSmi()) {
1267 int value = Smi::cast(object)->value();
1268 if (value < 0) return false;
1269 *index = value;
1270 return true;
1271 }
1272 if (object->IsHeapNumber()) {
1273 double value = HeapNumber::cast(object)->value();
1274 uint32_t uint_value = static_cast<uint32_t>(value);
1275 if (value == static_cast<double>(uint_value)) {
1276 *index = uint_value;
1277 return true;
1278 }
1279 }
1280 return false;
1281 }
1282
1283
IsStringObjectWithCharacterAt(uint32_t index)1284 bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1285 if (!this->IsJSValue()) return false;
1286
1287 JSValue* js_value = JSValue::cast(this);
1288 if (!js_value->value()->IsString()) return false;
1289
1290 String* str = String::cast(js_value->value());
1291 if (index >= (uint32_t)str->length()) return false;
1292
1293 return true;
1294 }
1295
1296
get(int index)1297 Object* FixedArray::get(int index) {
1298 ASSERT(index >= 0 && index < this->length());
1299 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1300 }
1301
1302
set(int index,Smi * value)1303 void FixedArray::set(int index, Smi* value) {
1304 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1305 int offset = kHeaderSize + index * kPointerSize;
1306 WRITE_FIELD(this, offset, value);
1307 }
1308
1309
set(int index,Object * value)1310 void FixedArray::set(int index, Object* value) {
1311 ASSERT(index >= 0 && index < this->length());
1312 int offset = kHeaderSize + index * kPointerSize;
1313 WRITE_FIELD(this, offset, value);
1314 WRITE_BARRIER(this, offset);
1315 }
1316
1317
GetWriteBarrierMode()1318 WriteBarrierMode HeapObject::GetWriteBarrierMode() {
1319 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1320 return UPDATE_WRITE_BARRIER;
1321 }
1322
1323
set(int index,Object * value,WriteBarrierMode mode)1324 void FixedArray::set(int index,
1325 Object* value,
1326 WriteBarrierMode mode) {
1327 ASSERT(index >= 0 && index < this->length());
1328 int offset = kHeaderSize + index * kPointerSize;
1329 WRITE_FIELD(this, offset, value);
1330 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1331 }
1332
1333
fast_set(FixedArray * array,int index,Object * value)1334 void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1335 ASSERT(index >= 0 && index < array->length());
1336 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1337 }
1338
1339
set_undefined(int index)1340 void FixedArray::set_undefined(int index) {
1341 ASSERT(index >= 0 && index < this->length());
1342 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1343 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1344 Heap::undefined_value());
1345 }
1346
1347
set_null(int index)1348 void FixedArray::set_null(int index) {
1349 ASSERT(index >= 0 && index < this->length());
1350 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1351 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1352 }
1353
1354
set_the_hole(int index)1355 void FixedArray::set_the_hole(int index) {
1356 ASSERT(index >= 0 && index < this->length());
1357 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1358 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1359 }
1360
1361
IsEmpty()1362 bool DescriptorArray::IsEmpty() {
1363 ASSERT(this == Heap::empty_descriptor_array() ||
1364 this->length() > 2);
1365 return this == Heap::empty_descriptor_array();
1366 }
1367
1368
fast_swap(FixedArray * array,int first,int second)1369 void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1370 Object* tmp = array->get(first);
1371 fast_set(array, first, array->get(second));
1372 fast_set(array, second, tmp);
1373 }
1374
1375
Search(String * name)1376 int DescriptorArray::Search(String* name) {
1377 SLOW_ASSERT(IsSortedNoDuplicates());
1378
1379 // Check for empty descriptor array.
1380 int nof = number_of_descriptors();
1381 if (nof == 0) return kNotFound;
1382
1383 // Fast case: do linear search for small arrays.
1384 const int kMaxElementsForLinearSearch = 8;
1385 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1386 return LinearSearch(name, nof);
1387 }
1388
1389 // Slow case: perform binary search.
1390 return BinarySearch(name, 0, nof - 1);
1391 }
1392
1393
GetKey(int descriptor_number)1394 String* DescriptorArray::GetKey(int descriptor_number) {
1395 ASSERT(descriptor_number < number_of_descriptors());
1396 return String::cast(get(ToKeyIndex(descriptor_number)));
1397 }
1398
1399
GetValue(int descriptor_number)1400 Object* DescriptorArray::GetValue(int descriptor_number) {
1401 ASSERT(descriptor_number < number_of_descriptors());
1402 return GetContentArray()->get(ToValueIndex(descriptor_number));
1403 }
1404
1405
GetDetails(int descriptor_number)1406 Smi* DescriptorArray::GetDetails(int descriptor_number) {
1407 ASSERT(descriptor_number < number_of_descriptors());
1408 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1409 }
1410
1411
GetType(int descriptor_number)1412 PropertyType DescriptorArray::GetType(int descriptor_number) {
1413 ASSERT(descriptor_number < number_of_descriptors());
1414 return PropertyDetails(GetDetails(descriptor_number)).type();
1415 }
1416
1417
GetFieldIndex(int descriptor_number)1418 int DescriptorArray::GetFieldIndex(int descriptor_number) {
1419 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1420 }
1421
1422
GetConstantFunction(int descriptor_number)1423 JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1424 return JSFunction::cast(GetValue(descriptor_number));
1425 }
1426
1427
GetCallbacksObject(int descriptor_number)1428 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1429 ASSERT(GetType(descriptor_number) == CALLBACKS);
1430 return GetValue(descriptor_number);
1431 }
1432
1433
GetCallbacks(int descriptor_number)1434 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1435 ASSERT(GetType(descriptor_number) == CALLBACKS);
1436 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1437 return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1438 }
1439
1440
IsProperty(int descriptor_number)1441 bool DescriptorArray::IsProperty(int descriptor_number) {
1442 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1443 }
1444
1445
IsTransition(int descriptor_number)1446 bool DescriptorArray::IsTransition(int descriptor_number) {
1447 PropertyType t = GetType(descriptor_number);
1448 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1449 }
1450
1451
IsNullDescriptor(int descriptor_number)1452 bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1453 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1454 }
1455
1456
IsDontEnum(int descriptor_number)1457 bool DescriptorArray::IsDontEnum(int descriptor_number) {
1458 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1459 }
1460
1461
Get(int descriptor_number,Descriptor * desc)1462 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1463 desc->Init(GetKey(descriptor_number),
1464 GetValue(descriptor_number),
1465 GetDetails(descriptor_number));
1466 }
1467
1468
Set(int descriptor_number,Descriptor * desc)1469 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1470 // Range check.
1471 ASSERT(descriptor_number < number_of_descriptors());
1472
1473 // Make sure non of the elements in desc are in new space.
1474 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1475 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1476
1477 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1478 FixedArray* content_array = GetContentArray();
1479 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1480 fast_set(content_array, ToDetailsIndex(descriptor_number),
1481 desc->GetDetails().AsSmi());
1482 }
1483
1484
CopyFrom(int index,DescriptorArray * src,int src_index)1485 void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1486 Descriptor desc;
1487 src->Get(src_index, &desc);
1488 Set(index, &desc);
1489 }
1490
1491
Swap(int first,int second)1492 void DescriptorArray::Swap(int first, int second) {
1493 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1494 FixedArray* content_array = GetContentArray();
1495 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1496 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1497 }
1498
1499
requires_slow_elements()1500 bool NumberDictionary::requires_slow_elements() {
1501 Object* max_index_object = get(kMaxNumberKeyIndex);
1502 if (!max_index_object->IsSmi()) return false;
1503 return 0 !=
1504 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1505 }
1506
max_number_key()1507 uint32_t NumberDictionary::max_number_key() {
1508 ASSERT(!requires_slow_elements());
1509 Object* max_index_object = get(kMaxNumberKeyIndex);
1510 if (!max_index_object->IsSmi()) return 0;
1511 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1512 return value >> kRequiresSlowElementsTagSize;
1513 }
1514
set_requires_slow_elements()1515 void NumberDictionary::set_requires_slow_elements() {
1516 set(kMaxNumberKeyIndex,
1517 Smi::FromInt(kRequiresSlowElementsMask),
1518 SKIP_WRITE_BARRIER);
1519 }
1520
1521
1522 // ------------------------------------
1523 // Cast operations
1524
1525
1526 CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(DescriptorArray)1527 CAST_ACCESSOR(DescriptorArray)
1528 CAST_ACCESSOR(SymbolTable)
1529 CAST_ACCESSOR(CompilationCacheTable)
1530 CAST_ACCESSOR(MapCache)
1531 CAST_ACCESSOR(String)
1532 CAST_ACCESSOR(SeqString)
1533 CAST_ACCESSOR(SeqAsciiString)
1534 CAST_ACCESSOR(SeqTwoByteString)
1535 CAST_ACCESSOR(ConsString)
1536 CAST_ACCESSOR(SlicedString)
1537 CAST_ACCESSOR(ExternalString)
1538 CAST_ACCESSOR(ExternalAsciiString)
1539 CAST_ACCESSOR(ExternalTwoByteString)
1540 CAST_ACCESSOR(JSObject)
1541 CAST_ACCESSOR(Smi)
1542 CAST_ACCESSOR(Failure)
1543 CAST_ACCESSOR(HeapObject)
1544 CAST_ACCESSOR(HeapNumber)
1545 CAST_ACCESSOR(Oddball)
1546 CAST_ACCESSOR(JSGlobalPropertyCell)
1547 CAST_ACCESSOR(SharedFunctionInfo)
1548 CAST_ACCESSOR(Map)
1549 CAST_ACCESSOR(JSFunction)
1550 CAST_ACCESSOR(GlobalObject)
1551 CAST_ACCESSOR(JSGlobalProxy)
1552 CAST_ACCESSOR(JSGlobalObject)
1553 CAST_ACCESSOR(JSBuiltinsObject)
1554 CAST_ACCESSOR(Code)
1555 CAST_ACCESSOR(JSArray)
1556 CAST_ACCESSOR(JSRegExp)
1557 CAST_ACCESSOR(Proxy)
1558 CAST_ACCESSOR(ByteArray)
1559 CAST_ACCESSOR(PixelArray)
1560 CAST_ACCESSOR(Struct)
1561
1562
1563 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1564 STRUCT_LIST(MAKE_STRUCT_CAST)
1565 #undef MAKE_STRUCT_CAST
1566
1567
1568 template <typename Shape, typename Key>
1569 HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
1570 ASSERT(obj->IsHashTable());
1571 return reinterpret_cast<HashTable*>(obj);
1572 }
1573
1574
INT_ACCESSORS(Array,length,kLengthOffset)1575 INT_ACCESSORS(Array, length, kLengthOffset)
1576
1577
1578 bool String::Equals(String* other) {
1579 if (other == this) return true;
1580 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1581 return false;
1582 }
1583 return SlowEquals(other);
1584 }
1585
1586
length()1587 int String::length() {
1588 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1589
1590 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1591 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1592 ASSERT(kLongStringTag == 0);
1593
1594 return len >> (StringShape(this).size_tag() + kLongLengthShift);
1595 }
1596
1597
set_length(int value)1598 void String::set_length(int value) {
1599 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1600 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1601 ASSERT(kLongStringTag == 0);
1602
1603 WRITE_INT_FIELD(this,
1604 kLengthOffset,
1605 value << (StringShape(this).size_tag() + kLongLengthShift));
1606 }
1607
1608
length_field()1609 uint32_t String::length_field() {
1610 return READ_UINT32_FIELD(this, kLengthOffset);
1611 }
1612
1613
set_length_field(uint32_t value)1614 void String::set_length_field(uint32_t value) {
1615 WRITE_UINT32_FIELD(this, kLengthOffset, value);
1616 }
1617
1618
TryFlattenIfNotFlat()1619 Object* String::TryFlattenIfNotFlat() {
1620 // We don't need to flatten strings that are already flat. Since this code
1621 // is inlined, it can be helpful in the flat case to not call out to Flatten.
1622 if (!IsFlat()) {
1623 return TryFlatten();
1624 }
1625 return this;
1626 }
1627
1628
Get(int index)1629 uint16_t String::Get(int index) {
1630 ASSERT(index >= 0 && index < length());
1631 switch (StringShape(this).full_representation_tag()) {
1632 case kSeqStringTag | kAsciiStringTag:
1633 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1634 case kSeqStringTag | kTwoByteStringTag:
1635 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1636 case kConsStringTag | kAsciiStringTag:
1637 case kConsStringTag | kTwoByteStringTag:
1638 return ConsString::cast(this)->ConsStringGet(index);
1639 case kSlicedStringTag | kAsciiStringTag:
1640 case kSlicedStringTag | kTwoByteStringTag:
1641 return SlicedString::cast(this)->SlicedStringGet(index);
1642 case kExternalStringTag | kAsciiStringTag:
1643 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1644 case kExternalStringTag | kTwoByteStringTag:
1645 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1646 default:
1647 break;
1648 }
1649
1650 UNREACHABLE();
1651 return 0;
1652 }
1653
1654
Set(int index,uint16_t value)1655 void String::Set(int index, uint16_t value) {
1656 ASSERT(index >= 0 && index < length());
1657 ASSERT(StringShape(this).IsSequential());
1658
1659 return this->IsAsciiRepresentation()
1660 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1661 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
1662 }
1663
1664
IsFlat()1665 bool String::IsFlat() {
1666 switch (StringShape(this).representation_tag()) {
1667 case kConsStringTag: {
1668 String* second = ConsString::cast(this)->second();
1669 // Only flattened strings have second part empty.
1670 return second->length() == 0;
1671 }
1672 case kSlicedStringTag: {
1673 StringRepresentationTag tag =
1674 StringShape(SlicedString::cast(this)->buffer()).representation_tag();
1675 return tag == kSeqStringTag || tag == kExternalStringTag;
1676 }
1677 default:
1678 return true;
1679 }
1680 }
1681
1682
SeqAsciiStringGet(int index)1683 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
1684 ASSERT(index >= 0 && index < length());
1685 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1686 }
1687
1688
SeqAsciiStringSet(int index,uint16_t value)1689 void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
1690 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1691 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1692 static_cast<byte>(value));
1693 }
1694
1695
GetCharsAddress()1696 Address SeqAsciiString::GetCharsAddress() {
1697 return FIELD_ADDR(this, kHeaderSize);
1698 }
1699
1700
GetChars()1701 char* SeqAsciiString::GetChars() {
1702 return reinterpret_cast<char*>(GetCharsAddress());
1703 }
1704
1705
GetCharsAddress()1706 Address SeqTwoByteString::GetCharsAddress() {
1707 return FIELD_ADDR(this, kHeaderSize);
1708 }
1709
1710
GetChars()1711 uc16* SeqTwoByteString::GetChars() {
1712 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1713 }
1714
1715
SeqTwoByteStringGet(int index)1716 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
1717 ASSERT(index >= 0 && index < length());
1718 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1719 }
1720
1721
SeqTwoByteStringSet(int index,uint16_t value)1722 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
1723 ASSERT(index >= 0 && index < length());
1724 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1725 }
1726
1727
SeqTwoByteStringSize(InstanceType instance_type)1728 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
1729 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1730
1731 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1732 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1733 ASSERT(kLongStringTag == 0);
1734
1735 // Use the map (and not 'this') to compute the size tag, since
1736 // TwoByteStringSize is called during GC when maps are encoded.
1737 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
1738
1739 return SizeFor(length);
1740 }
1741
1742
SeqAsciiStringSize(InstanceType instance_type)1743 int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
1744 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1745
1746 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
1747 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
1748 ASSERT(kLongStringTag == 0);
1749
1750 // Use the map (and not 'this') to compute the size tag, since
1751 // AsciiStringSize is called during GC when maps are encoded.
1752 length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
1753
1754 return SizeFor(length);
1755 }
1756
1757
first()1758 String* ConsString::first() {
1759 return String::cast(READ_FIELD(this, kFirstOffset));
1760 }
1761
1762
unchecked_first()1763 Object* ConsString::unchecked_first() {
1764 return READ_FIELD(this, kFirstOffset);
1765 }
1766
1767
set_first(String * value,WriteBarrierMode mode)1768 void ConsString::set_first(String* value, WriteBarrierMode mode) {
1769 WRITE_FIELD(this, kFirstOffset, value);
1770 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
1771 }
1772
1773
second()1774 String* ConsString::second() {
1775 return String::cast(READ_FIELD(this, kSecondOffset));
1776 }
1777
1778
unchecked_second()1779 Object* ConsString::unchecked_second() {
1780 return READ_FIELD(this, kSecondOffset);
1781 }
1782
1783
set_second(String * value,WriteBarrierMode mode)1784 void ConsString::set_second(String* value, WriteBarrierMode mode) {
1785 WRITE_FIELD(this, kSecondOffset, value);
1786 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
1787 }
1788
1789
buffer()1790 String* SlicedString::buffer() {
1791 return String::cast(READ_FIELD(this, kBufferOffset));
1792 }
1793
1794
set_buffer(String * buffer)1795 void SlicedString::set_buffer(String* buffer) {
1796 WRITE_FIELD(this, kBufferOffset, buffer);
1797 WRITE_BARRIER(this, kBufferOffset);
1798 }
1799
1800
start()1801 int SlicedString::start() {
1802 return READ_INT_FIELD(this, kStartOffset);
1803 }
1804
1805
set_start(int start)1806 void SlicedString::set_start(int start) {
1807 WRITE_INT_FIELD(this, kStartOffset, start);
1808 }
1809
1810
resource()1811 ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1812 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1813 }
1814
1815
set_resource(ExternalAsciiString::Resource * resource)1816 void ExternalAsciiString::set_resource(
1817 ExternalAsciiString::Resource* resource) {
1818 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1819 }
1820
1821
StringMap(int length)1822 Map* ExternalAsciiString::StringMap(int length) {
1823 Map* map;
1824 // Number of characters: determines the map.
1825 if (length <= String::kMaxShortStringSize) {
1826 map = Heap::short_external_ascii_string_map();
1827 } else if (length <= String::kMaxMediumStringSize) {
1828 map = Heap::medium_external_ascii_string_map();
1829 } else {
1830 map = Heap::long_external_ascii_string_map();
1831 }
1832 return map;
1833 }
1834
1835
SymbolMap(int length)1836 Map* ExternalAsciiString::SymbolMap(int length) {
1837 Map* map;
1838 // Number of characters: determines the map.
1839 if (length <= String::kMaxShortStringSize) {
1840 map = Heap::short_external_ascii_symbol_map();
1841 } else if (length <= String::kMaxMediumStringSize) {
1842 map = Heap::medium_external_ascii_symbol_map();
1843 } else {
1844 map = Heap::long_external_ascii_symbol_map();
1845 }
1846 return map;
1847 }
1848
1849
resource()1850 ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1851 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1852 }
1853
1854
set_resource(ExternalTwoByteString::Resource * resource)1855 void ExternalTwoByteString::set_resource(
1856 ExternalTwoByteString::Resource* resource) {
1857 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1858 }
1859
1860
StringMap(int length)1861 Map* ExternalTwoByteString::StringMap(int length) {
1862 Map* map;
1863 // Number of characters: determines the map.
1864 if (length <= String::kMaxShortStringSize) {
1865 map = Heap::short_external_string_map();
1866 } else if (length <= String::kMaxMediumStringSize) {
1867 map = Heap::medium_external_string_map();
1868 } else {
1869 map = Heap::long_external_string_map();
1870 }
1871 return map;
1872 }
1873
1874
SymbolMap(int length)1875 Map* ExternalTwoByteString::SymbolMap(int length) {
1876 Map* map;
1877 // Number of characters: determines the map.
1878 if (length <= String::kMaxShortStringSize) {
1879 map = Heap::short_external_symbol_map();
1880 } else if (length <= String::kMaxMediumStringSize) {
1881 map = Heap::medium_external_symbol_map();
1882 } else {
1883 map = Heap::long_external_symbol_map();
1884 }
1885 return map;
1886 }
1887
1888
get(int index)1889 byte ByteArray::get(int index) {
1890 ASSERT(index >= 0 && index < this->length());
1891 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1892 }
1893
1894
set(int index,byte value)1895 void ByteArray::set(int index, byte value) {
1896 ASSERT(index >= 0 && index < this->length());
1897 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1898 }
1899
1900
get_int(int index)1901 int ByteArray::get_int(int index) {
1902 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1903 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1904 }
1905
1906
FromDataStartAddress(Address address)1907 ByteArray* ByteArray::FromDataStartAddress(Address address) {
1908 ASSERT_TAG_ALIGNED(address);
1909 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1910 }
1911
1912
GetDataStartAddress()1913 Address ByteArray::GetDataStartAddress() {
1914 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1915 }
1916
1917
external_pointer()1918 uint8_t* PixelArray::external_pointer() {
1919 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1920 return reinterpret_cast<uint8_t*>(ptr);
1921 }
1922
1923
set_external_pointer(uint8_t * value,WriteBarrierMode mode)1924 void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1925 intptr_t ptr = reinterpret_cast<intptr_t>(value);
1926 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1927 }
1928
1929
get(int index)1930 uint8_t PixelArray::get(int index) {
1931 ASSERT((index >= 0) && (index < this->length()));
1932 uint8_t* ptr = external_pointer();
1933 return ptr[index];
1934 }
1935
1936
set(int index,uint8_t value)1937 void PixelArray::set(int index, uint8_t value) {
1938 ASSERT((index >= 0) && (index < this->length()));
1939 uint8_t* ptr = external_pointer();
1940 ptr[index] = value;
1941 }
1942
1943
instance_size()1944 int Map::instance_size() {
1945 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1946 }
1947
1948
inobject_properties()1949 int Map::inobject_properties() {
1950 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
1951 }
1952
1953
pre_allocated_property_fields()1954 int Map::pre_allocated_property_fields() {
1955 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
1956 }
1957
1958
SizeFromMap(Map * map)1959 int HeapObject::SizeFromMap(Map* map) {
1960 InstanceType instance_type = map->instance_type();
1961 // Only inline the most frequent cases.
1962 if (instance_type == JS_OBJECT_TYPE ||
1963 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1964 (kStringTag | kConsStringTag) ||
1965 instance_type == JS_ARRAY_TYPE) return map->instance_size();
1966 if (instance_type == FIXED_ARRAY_TYPE) {
1967 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1968 }
1969 if (instance_type == BYTE_ARRAY_TYPE) {
1970 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1971 }
1972 // Otherwise do the general size computation.
1973 return SlowSizeFromMap(map);
1974 }
1975
1976
set_instance_size(int value)1977 void Map::set_instance_size(int value) {
1978 ASSERT_EQ(0, value & (kPointerSize - 1));
1979 value >>= kPointerSizeLog2;
1980 ASSERT(0 <= value && value < 256);
1981 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1982 }
1983
1984
set_inobject_properties(int value)1985 void Map::set_inobject_properties(int value) {
1986 ASSERT(0 <= value && value < 256);
1987 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1988 }
1989
1990
set_pre_allocated_property_fields(int value)1991 void Map::set_pre_allocated_property_fields(int value) {
1992 ASSERT(0 <= value && value < 256);
1993 WRITE_BYTE_FIELD(this,
1994 kPreAllocatedPropertyFieldsOffset,
1995 static_cast<byte>(value));
1996 }
1997
1998
instance_type()1999 InstanceType Map::instance_type() {
2000 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2001 }
2002
2003
set_instance_type(InstanceType value)2004 void Map::set_instance_type(InstanceType value) {
2005 ASSERT(0 <= value && value < 256);
2006 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2007 }
2008
2009
unused_property_fields()2010 int Map::unused_property_fields() {
2011 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2012 }
2013
2014
set_unused_property_fields(int value)2015 void Map::set_unused_property_fields(int value) {
2016 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2017 }
2018
2019
bit_field()2020 byte Map::bit_field() {
2021 return READ_BYTE_FIELD(this, kBitFieldOffset);
2022 }
2023
2024
set_bit_field(byte value)2025 void Map::set_bit_field(byte value) {
2026 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2027 }
2028
2029
bit_field2()2030 byte Map::bit_field2() {
2031 return READ_BYTE_FIELD(this, kBitField2Offset);
2032 }
2033
2034
set_bit_field2(byte value)2035 void Map::set_bit_field2(byte value) {
2036 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2037 }
2038
2039
set_non_instance_prototype(bool value)2040 void Map::set_non_instance_prototype(bool value) {
2041 if (value) {
2042 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2043 } else {
2044 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2045 }
2046 }
2047
2048
has_non_instance_prototype()2049 bool Map::has_non_instance_prototype() {
2050 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2051 }
2052
2053
set_is_access_check_needed(bool access_check_needed)2054 void Map::set_is_access_check_needed(bool access_check_needed) {
2055 if (access_check_needed) {
2056 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2057 } else {
2058 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2059 }
2060 }
2061
2062
is_access_check_needed()2063 bool Map::is_access_check_needed() {
2064 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2065 }
2066
2067
flags()2068 Code::Flags Code::flags() {
2069 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2070 }
2071
2072
set_flags(Code::Flags flags)2073 void Code::set_flags(Code::Flags flags) {
2074 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
2075 // Make sure that all call stubs have an arguments count.
2076 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
2077 ExtractArgumentsCountFromFlags(flags) >= 0);
2078 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2079 }
2080
2081
kind()2082 Code::Kind Code::kind() {
2083 return ExtractKindFromFlags(flags());
2084 }
2085
2086
ic_in_loop()2087 InLoopFlag Code::ic_in_loop() {
2088 return ExtractICInLoopFromFlags(flags());
2089 }
2090
2091
ic_state()2092 InlineCacheState Code::ic_state() {
2093 InlineCacheState result = ExtractICStateFromFlags(flags());
2094 // Only allow uninitialized or debugger states for non-IC code
2095 // objects. This is used in the debugger to determine whether or not
2096 // a call to code object has been replaced with a debug break call.
2097 ASSERT(is_inline_cache_stub() ||
2098 result == UNINITIALIZED ||
2099 result == DEBUG_BREAK ||
2100 result == DEBUG_PREPARE_STEP_IN);
2101 return result;
2102 }
2103
2104
type()2105 PropertyType Code::type() {
2106 ASSERT(ic_state() == MONOMORPHIC);
2107 return ExtractTypeFromFlags(flags());
2108 }
2109
2110
arguments_count()2111 int Code::arguments_count() {
2112 ASSERT(is_call_stub() || kind() == STUB);
2113 return ExtractArgumentsCountFromFlags(flags());
2114 }
2115
2116
major_key()2117 CodeStub::Major Code::major_key() {
2118 ASSERT(kind() == STUB);
2119 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2120 kStubMajorKeyOffset));
2121 }
2122
2123
set_major_key(CodeStub::Major major)2124 void Code::set_major_key(CodeStub::Major major) {
2125 ASSERT(kind() == STUB);
2126 ASSERT(0 <= major && major < 256);
2127 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2128 }
2129
2130
is_inline_cache_stub()2131 bool Code::is_inline_cache_stub() {
2132 Kind kind = this->kind();
2133 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2134 }
2135
2136
ComputeFlags(Kind kind,InLoopFlag in_loop,InlineCacheState ic_state,PropertyType type,int argc)2137 Code::Flags Code::ComputeFlags(Kind kind,
2138 InLoopFlag in_loop,
2139 InlineCacheState ic_state,
2140 PropertyType type,
2141 int argc) {
2142 // Compute the bit mask.
2143 int bits = kind << kFlagsKindShift;
2144 if (in_loop) bits |= kFlagsICInLoopMask;
2145 bits |= ic_state << kFlagsICStateShift;
2146 bits |= type << kFlagsTypeShift;
2147 bits |= argc << kFlagsArgumentsCountShift;
2148 // Cast to flags and validate result before returning it.
2149 Flags result = static_cast<Flags>(bits);
2150 ASSERT(ExtractKindFromFlags(result) == kind);
2151 ASSERT(ExtractICStateFromFlags(result) == ic_state);
2152 ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
2153 ASSERT(ExtractTypeFromFlags(result) == type);
2154 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2155 return result;
2156 }
2157
2158
ComputeMonomorphicFlags(Kind kind,PropertyType type,InLoopFlag in_loop,int argc)2159 Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2160 PropertyType type,
2161 InLoopFlag in_loop,
2162 int argc) {
2163 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
2164 }
2165
2166
ExtractKindFromFlags(Flags flags)2167 Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2168 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2169 return static_cast<Kind>(bits);
2170 }
2171
2172
ExtractICStateFromFlags(Flags flags)2173 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2174 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
2175 return static_cast<InlineCacheState>(bits);
2176 }
2177
2178
ExtractICInLoopFromFlags(Flags flags)2179 InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2180 int bits = (flags & kFlagsICInLoopMask);
2181 return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2182 }
2183
2184
ExtractTypeFromFlags(Flags flags)2185 PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2186 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2187 return static_cast<PropertyType>(bits);
2188 }
2189
2190
ExtractArgumentsCountFromFlags(Flags flags)2191 int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2192 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2193 }
2194
2195
RemoveTypeFromFlags(Flags flags)2196 Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2197 int bits = flags & ~kFlagsTypeMask;
2198 return static_cast<Flags>(bits);
2199 }
2200
2201
GetCodeFromTargetAddress(Address address)2202 Code* Code::GetCodeFromTargetAddress(Address address) {
2203 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2204 // GetCodeFromTargetAddress might be called when marking objects during mark
2205 // sweep. reinterpret_cast is therefore used instead of the more appropriate
2206 // Code::cast. Code::cast does not work when the object's map is
2207 // marked.
2208 Code* result = reinterpret_cast<Code*>(code);
2209 return result;
2210 }
2211
2212
prototype()2213 Object* Map::prototype() {
2214 return READ_FIELD(this, kPrototypeOffset);
2215 }
2216
2217
set_prototype(Object * value,WriteBarrierMode mode)2218 void Map::set_prototype(Object* value, WriteBarrierMode mode) {
2219 ASSERT(value->IsNull() || value->IsJSObject());
2220 WRITE_FIELD(this, kPrototypeOffset, value);
2221 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
2222 }
2223
2224
ACCESSORS(Map,instance_descriptors,DescriptorArray,kInstanceDescriptorsOffset)2225 ACCESSORS(Map, instance_descriptors, DescriptorArray,
2226 kInstanceDescriptorsOffset)
2227 ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2228 ACCESSORS(Map, constructor, Object, kConstructorOffset)
2229
2230 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2231 ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2232
2233 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2234 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
2235 ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
2236
2237 ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
2238
2239 ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2240 ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2241 ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2242 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2243 ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2244
2245 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2246 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2247 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2248
2249 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2250 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2251 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2252 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2253 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2254 ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2255
2256 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2257 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2258
2259 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2260 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2261
2262 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2263 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
2264 ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2265 kPropertyAccessorsOffset)
2266 ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2267 kPrototypeTemplateOffset)
2268 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2269 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2270 kNamedPropertyHandlerOffset)
2271 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2272 kIndexedPropertyHandlerOffset)
2273 ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2274 kInstanceTemplateOffset)
2275 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2276 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
2277 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2278 kInstanceCallHandlerOffset)
2279 ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2280 kAccessCheckInfoOffset)
2281 ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2282
2283 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
2284 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2285 kInternalFieldCountOffset)
2286
2287 ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2288 ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2289
2290 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2291
2292 ACCESSORS(Script, source, Object, kSourceOffset)
2293 ACCESSORS(Script, name, Object, kNameOffset)
2294 ACCESSORS(Script, id, Object, kIdOffset)
2295 ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2296 ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
2297 ACCESSORS(Script, data, Object, kDataOffset)
2298 ACCESSORS(Script, context_data, Object, kContextOffset)
2299 ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2300 ACCESSORS(Script, type, Smi, kTypeOffset)
2301 ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
2302 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
2303 ACCESSORS(Script, eval_from_function, Object, kEvalFromFunctionOffset)
2304 ACCESSORS(Script, eval_from_instructions_offset, Smi,
2305 kEvalFrominstructionsOffsetOffset)
2306
2307 #ifdef ENABLE_DEBUGGER_SUPPORT
2308 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2309 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2310 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2311 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2312
2313 ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2314 ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2315 ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2316 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2317 #endif
2318
2319 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
2320 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2321 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2322 kInstanceClassNameOffset)
2323 ACCESSORS(SharedFunctionInfo, function_data, Object,
2324 kExternalReferenceDataOffset)
2325 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2326 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
2327 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
2328 ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2329 kThisPropertyAssignmentsOffset)
2330
2331 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2332 kHiddenPrototypeBit)
2333 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2334 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2335 kNeedsAccessCheckBit)
2336 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2337 kIsExpressionBit)
2338 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2339 kIsTopLevelBit)
2340 BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2341 has_only_this_property_assignments,
2342 kHasOnlyThisPropertyAssignments)
2343 BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2344 has_only_simple_this_property_assignments,
2345 kHasOnlySimpleThisPropertyAssignments)
2346
2347
2348 INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2349 INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2350 kFormalParameterCountOffset)
2351 INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2352 kExpectedNofPropertiesOffset)
2353 INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2354 kStartPositionAndTypeOffset)
2355 INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2356 INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2357 kFunctionTokenPositionOffset)
2358 INT_ACCESSORS(SharedFunctionInfo, compiler_hints,
2359 kCompilerHintsOffset)
2360 INT_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
2361 kThisPropertyAssignmentsCountOffset)
2362
2363
2364 void SharedFunctionInfo::DontAdaptArguments() {
2365 ASSERT(code()->kind() == Code::BUILTIN);
2366 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2367 }
2368
2369
start_position()2370 int SharedFunctionInfo::start_position() {
2371 return start_position_and_type() >> kStartPositionShift;
2372 }
2373
2374
set_start_position(int start_position)2375 void SharedFunctionInfo::set_start_position(int start_position) {
2376 set_start_position_and_type((start_position << kStartPositionShift)
2377 | (start_position_and_type() & ~kStartPositionMask));
2378 }
2379
2380
code()2381 Code* SharedFunctionInfo::code() {
2382 return Code::cast(READ_FIELD(this, kCodeOffset));
2383 }
2384
2385
set_code(Code * value,WriteBarrierMode mode)2386 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
2387 WRITE_FIELD(this, kCodeOffset, value);
2388 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
2389 }
2390
2391
is_compiled()2392 bool SharedFunctionInfo::is_compiled() {
2393 // TODO(1242782): Create a code kind for uncompiled code.
2394 return code()->kind() != Code::STUB;
2395 }
2396
2397
IsBoilerplate()2398 bool JSFunction::IsBoilerplate() {
2399 return map() == Heap::boilerplate_function_map();
2400 }
2401
2402
IsBuiltin()2403 bool JSFunction::IsBuiltin() {
2404 return context()->global()->IsJSBuiltinsObject();
2405 }
2406
2407
IsLoaded()2408 bool JSObject::IsLoaded() {
2409 return !map()->needs_loading();
2410 }
2411
2412
code()2413 Code* JSFunction::code() {
2414 return shared()->code();
2415 }
2416
2417
set_code(Code * value)2418 void JSFunction::set_code(Code* value) {
2419 shared()->set_code(value);
2420 }
2421
2422
context()2423 Context* JSFunction::context() {
2424 return Context::cast(READ_FIELD(this, kContextOffset));
2425 }
2426
2427
unchecked_context()2428 Object* JSFunction::unchecked_context() {
2429 return READ_FIELD(this, kContextOffset);
2430 }
2431
2432
set_context(Object * value)2433 void JSFunction::set_context(Object* value) {
2434 ASSERT(value == Heap::undefined_value() || value->IsContext());
2435 WRITE_FIELD(this, kContextOffset, value);
2436 WRITE_BARRIER(this, kContextOffset);
2437 }
2438
ACCESSORS(JSFunction,prototype_or_initial_map,Object,kPrototypeOrInitialMapOffset)2439 ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2440 kPrototypeOrInitialMapOffset)
2441
2442
2443 Map* JSFunction::initial_map() {
2444 return Map::cast(prototype_or_initial_map());
2445 }
2446
2447
set_initial_map(Map * value)2448 void JSFunction::set_initial_map(Map* value) {
2449 set_prototype_or_initial_map(value);
2450 }
2451
2452
has_initial_map()2453 bool JSFunction::has_initial_map() {
2454 return prototype_or_initial_map()->IsMap();
2455 }
2456
2457
has_instance_prototype()2458 bool JSFunction::has_instance_prototype() {
2459 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2460 }
2461
2462
has_prototype()2463 bool JSFunction::has_prototype() {
2464 return map()->has_non_instance_prototype() || has_instance_prototype();
2465 }
2466
2467
instance_prototype()2468 Object* JSFunction::instance_prototype() {
2469 ASSERT(has_instance_prototype());
2470 if (has_initial_map()) return initial_map()->prototype();
2471 // When there is no initial map and the prototype is a JSObject, the
2472 // initial map field is used for the prototype field.
2473 return prototype_or_initial_map();
2474 }
2475
2476
prototype()2477 Object* JSFunction::prototype() {
2478 ASSERT(has_prototype());
2479 // If the function's prototype property has been set to a non-JSObject
2480 // value, that value is stored in the constructor field of the map.
2481 if (map()->has_non_instance_prototype()) return map()->constructor();
2482 return instance_prototype();
2483 }
2484
2485
is_compiled()2486 bool JSFunction::is_compiled() {
2487 return shared()->is_compiled();
2488 }
2489
2490
NumberOfLiterals()2491 int JSFunction::NumberOfLiterals() {
2492 return literals()->length();
2493 }
2494
2495
javascript_builtin(Builtins::JavaScript id)2496 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2497 ASSERT(0 <= id && id < kJSBuiltinsCount);
2498 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2499 }
2500
2501
set_javascript_builtin(Builtins::JavaScript id,Object * value)2502 void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2503 Object* value) {
2504 ASSERT(0 <= id && id < kJSBuiltinsCount);
2505 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2506 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2507 }
2508
2509
proxy()2510 Address Proxy::proxy() {
2511 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
2512 }
2513
2514
set_proxy(Address value)2515 void Proxy::set_proxy(Address value) {
2516 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
2517 }
2518
2519
ProxyIterateBody(ObjectVisitor * visitor)2520 void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2521 visitor->VisitExternalReference(
2522 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2523 }
2524
2525
ACCESSORS(JSValue,value,Object,kValueOffset)2526 ACCESSORS(JSValue, value, Object, kValueOffset)
2527
2528
2529 JSValue* JSValue::cast(Object* obj) {
2530 ASSERT(obj->IsJSValue());
2531 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2532 return reinterpret_cast<JSValue*>(obj);
2533 }
2534
2535
INT_ACCESSORS(Code,instruction_size,kInstructionSizeOffset)2536 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2537 INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2538 INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2539
2540
2541 Code::ICTargetState Code::ic_flag() {
2542 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
2543 }
2544
2545
set_ic_flag(ICTargetState value)2546 void Code::set_ic_flag(ICTargetState value) {
2547 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
2548 }
2549
2550
instruction_start()2551 byte* Code::instruction_start() {
2552 return FIELD_ADDR(this, kHeaderSize);
2553 }
2554
2555
body_size()2556 int Code::body_size() {
2557 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2558 }
2559
2560
relocation_start()2561 byte* Code::relocation_start() {
2562 return FIELD_ADDR(this, kHeaderSize + instruction_size());
2563 }
2564
2565
entry()2566 byte* Code::entry() {
2567 return instruction_start();
2568 }
2569
2570
contains(byte * pc)2571 bool Code::contains(byte* pc) {
2572 return (instruction_start() <= pc) &&
2573 (pc < instruction_start() + instruction_size());
2574 }
2575
2576
sinfo_start()2577 byte* Code::sinfo_start() {
2578 return FIELD_ADDR(this, kHeaderSize + body_size());
2579 }
2580
2581
ACCESSORS(JSArray,length,Object,kLengthOffset)2582 ACCESSORS(JSArray, length, Object, kLengthOffset)
2583
2584
2585 ACCESSORS(JSRegExp, data, Object, kDataOffset)
2586
2587
2588 JSRegExp::Type JSRegExp::TypeTag() {
2589 Object* data = this->data();
2590 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2591 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2592 return static_cast<JSRegExp::Type>(smi->value());
2593 }
2594
2595
CaptureCount()2596 int JSRegExp::CaptureCount() {
2597 switch (TypeTag()) {
2598 case ATOM:
2599 return 0;
2600 case IRREGEXP:
2601 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2602 default:
2603 UNREACHABLE();
2604 return -1;
2605 }
2606 }
2607
2608
GetFlags()2609 JSRegExp::Flags JSRegExp::GetFlags() {
2610 ASSERT(this->data()->IsFixedArray());
2611 Object* data = this->data();
2612 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2613 return Flags(smi->value());
2614 }
2615
2616
Pattern()2617 String* JSRegExp::Pattern() {
2618 ASSERT(this->data()->IsFixedArray());
2619 Object* data = this->data();
2620 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2621 return pattern;
2622 }
2623
2624
DataAt(int index)2625 Object* JSRegExp::DataAt(int index) {
2626 ASSERT(TypeTag() != NOT_COMPILED);
2627 return FixedArray::cast(data())->get(index);
2628 }
2629
2630
SetDataAt(int index,Object * value)2631 void JSRegExp::SetDataAt(int index, Object* value) {
2632 ASSERT(TypeTag() != NOT_COMPILED);
2633 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
2634 FixedArray::cast(data())->set(index, value);
2635 }
2636
2637
GetElementsKind()2638 JSObject::ElementsKind JSObject::GetElementsKind() {
2639 Array* array = elements();
2640 if (array->IsFixedArray()) {
2641 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2642 if (array->map() == Heap::fixed_array_map()) {
2643 return FAST_ELEMENTS;
2644 }
2645 ASSERT(array->IsDictionary());
2646 return DICTIONARY_ELEMENTS;
2647 }
2648 ASSERT(array->IsPixelArray());
2649 return PIXEL_ELEMENTS;
2650 }
2651
2652
HasFastElements()2653 bool JSObject::HasFastElements() {
2654 return GetElementsKind() == FAST_ELEMENTS;
2655 }
2656
2657
HasDictionaryElements()2658 bool JSObject::HasDictionaryElements() {
2659 return GetElementsKind() == DICTIONARY_ELEMENTS;
2660 }
2661
2662
HasPixelElements()2663 bool JSObject::HasPixelElements() {
2664 return GetElementsKind() == PIXEL_ELEMENTS;
2665 }
2666
2667
HasNamedInterceptor()2668 bool JSObject::HasNamedInterceptor() {
2669 return map()->has_named_interceptor();
2670 }
2671
2672
HasIndexedInterceptor()2673 bool JSObject::HasIndexedInterceptor() {
2674 return map()->has_indexed_interceptor();
2675 }
2676
2677
property_dictionary()2678 StringDictionary* JSObject::property_dictionary() {
2679 ASSERT(!HasFastProperties());
2680 return StringDictionary::cast(properties());
2681 }
2682
2683
element_dictionary()2684 NumberDictionary* JSObject::element_dictionary() {
2685 ASSERT(HasDictionaryElements());
2686 return NumberDictionary::cast(elements());
2687 }
2688
2689
HasHashCode()2690 bool String::HasHashCode() {
2691 return (length_field() & kHashComputedMask) != 0;
2692 }
2693
2694
Hash()2695 uint32_t String::Hash() {
2696 // Fast case: has hash code already been computed?
2697 uint32_t field = length_field();
2698 if (field & kHashComputedMask) return field >> kHashShift;
2699 // Slow case: compute hash code and set it.
2700 return ComputeAndSetHash();
2701 }
2702
2703
StringHasher(int length)2704 StringHasher::StringHasher(int length)
2705 : length_(length),
2706 raw_running_hash_(0),
2707 array_index_(0),
2708 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2709 is_first_char_(true),
2710 is_valid_(true) { }
2711
2712
has_trivial_hash()2713 bool StringHasher::has_trivial_hash() {
2714 return length_ > String::kMaxMediumStringSize;
2715 }
2716
2717
AddCharacter(uc32 c)2718 void StringHasher::AddCharacter(uc32 c) {
2719 // Use the Jenkins one-at-a-time hash function to update the hash
2720 // for the given character.
2721 raw_running_hash_ += c;
2722 raw_running_hash_ += (raw_running_hash_ << 10);
2723 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2724 // Incremental array index computation.
2725 if (is_array_index_) {
2726 if (c < '0' || c > '9') {
2727 is_array_index_ = false;
2728 } else {
2729 int d = c - '0';
2730 if (is_first_char_) {
2731 is_first_char_ = false;
2732 if (c == '0' && length_ > 1) {
2733 is_array_index_ = false;
2734 return;
2735 }
2736 }
2737 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2738 is_array_index_ = false;
2739 } else {
2740 array_index_ = array_index_ * 10 + d;
2741 }
2742 }
2743 }
2744 }
2745
2746
AddCharacterNoIndex(uc32 c)2747 void StringHasher::AddCharacterNoIndex(uc32 c) {
2748 ASSERT(!is_array_index());
2749 raw_running_hash_ += c;
2750 raw_running_hash_ += (raw_running_hash_ << 10);
2751 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2752 }
2753
2754
GetHash()2755 uint32_t StringHasher::GetHash() {
2756 // Get the calculated raw hash value and do some more bit ops to distribute
2757 // the hash further. Ensure that we never return zero as the hash value.
2758 uint32_t result = raw_running_hash_;
2759 result += (result << 3);
2760 result ^= (result >> 11);
2761 result += (result << 15);
2762 if (result == 0) {
2763 result = 27;
2764 }
2765 return result;
2766 }
2767
2768
AsArrayIndex(uint32_t * index)2769 bool String::AsArrayIndex(uint32_t* index) {
2770 uint32_t field = length_field();
2771 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
2772 return SlowAsArrayIndex(index);
2773 }
2774
2775
GetPrototype()2776 Object* JSObject::GetPrototype() {
2777 return JSObject::cast(this)->map()->prototype();
2778 }
2779
2780
GetPropertyAttribute(String * key)2781 PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2782 return GetPropertyAttributeWithReceiver(this, key);
2783 }
2784
2785
HasElement(uint32_t index)2786 bool JSObject::HasElement(uint32_t index) {
2787 return HasElementWithReceiver(this, index);
2788 }
2789
2790
all_can_read()2791 bool AccessorInfo::all_can_read() {
2792 return BooleanBit::get(flag(), kAllCanReadBit);
2793 }
2794
2795
set_all_can_read(bool value)2796 void AccessorInfo::set_all_can_read(bool value) {
2797 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2798 }
2799
2800
all_can_write()2801 bool AccessorInfo::all_can_write() {
2802 return BooleanBit::get(flag(), kAllCanWriteBit);
2803 }
2804
2805
set_all_can_write(bool value)2806 void AccessorInfo::set_all_can_write(bool value) {
2807 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2808 }
2809
2810
prohibits_overwriting()2811 bool AccessorInfo::prohibits_overwriting() {
2812 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2813 }
2814
2815
set_prohibits_overwriting(bool value)2816 void AccessorInfo::set_prohibits_overwriting(bool value) {
2817 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2818 }
2819
2820
property_attributes()2821 PropertyAttributes AccessorInfo::property_attributes() {
2822 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2823 }
2824
2825
set_property_attributes(PropertyAttributes attributes)2826 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2827 ASSERT(AttributesField::is_valid(attributes));
2828 int rest_value = flag()->value() & ~AttributesField::mask();
2829 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2830 }
2831
2832 template<typename Shape, typename Key>
SetEntry(int entry,Object * key,Object * value,PropertyDetails details)2833 void Dictionary<Shape, Key>::SetEntry(int entry,
2834 Object* key,
2835 Object* value,
2836 PropertyDetails details) {
2837 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
2838 int index = HashTable<Shape, Key>::EntryToIndex(entry);
2839 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
2840 FixedArray::set(index, key, mode);
2841 FixedArray::set(index+1, value, mode);
2842 FixedArray::fast_set(this, index+2, details.AsSmi());
2843 }
2844
2845
ClearCodeCache()2846 void Map::ClearCodeCache() {
2847 // No write barrier is needed since empty_fixed_array is not in new space.
2848 // Please note this function is used during marking:
2849 // - MarkCompactCollector::MarkUnmarkedObject
2850 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
2851 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
2852 }
2853
2854
EnsureSize(int required_size)2855 void JSArray::EnsureSize(int required_size) {
2856 ASSERT(HasFastElements());
2857 if (elements()->length() >= required_size) return;
2858 Expand(required_size);
2859 }
2860
2861
SetContent(FixedArray * storage)2862 void JSArray::SetContent(FixedArray* storage) {
2863 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
2864 set_elements(storage);
2865 }
2866
2867
Copy()2868 Object* FixedArray::Copy() {
2869 if (length() == 0) return this;
2870 return Heap::CopyFixedArray(this);
2871 }
2872
2873
2874 #undef CAST_ACCESSOR
2875 #undef INT_ACCESSORS
2876 #undef SMI_ACCESSORS
2877 #undef ACCESSORS
2878 #undef FIELD_ADDR
2879 #undef READ_FIELD
2880 #undef WRITE_FIELD
2881 #undef WRITE_BARRIER
2882 #undef CONDITIONAL_WRITE_BARRIER
2883 #undef READ_MEMADDR_FIELD
2884 #undef WRITE_MEMADDR_FIELD
2885 #undef READ_DOUBLE_FIELD
2886 #undef WRITE_DOUBLE_FIELD
2887 #undef READ_INT_FIELD
2888 #undef WRITE_INT_FIELD
2889 #undef READ_SHORT_FIELD
2890 #undef WRITE_SHORT_FIELD
2891 #undef READ_BYTE_FIELD
2892 #undef WRITE_BYTE_FIELD
2893
2894
2895 } } // namespace v8::internal
2896
2897 #endif // V8_OBJECTS_INL_H_
2898