1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // Review notes:
6 //
7 // - The use of macros in these inline functions may seem superfluous
8 // but it is absolutely needed to make sure gcc generates optimal
9 // code. gcc is not happy when attempting to inline too deep.
10 //
11
12 #ifndef V8_OBJECTS_INL_H_
13 #define V8_OBJECTS_INL_H_
14
15 #include "src/base/atomicops.h"
16 #include "src/base/bits.h"
17 #include "src/contexts.h"
18 #include "src/conversions-inl.h"
19 #include "src/elements.h"
20 #include "src/factory.h"
21 #include "src/field-index-inl.h"
22 #include "src/heap/heap-inl.h"
23 #include "src/heap/heap.h"
24 #include "src/heap/incremental-marking.h"
25 #include "src/heap/objects-visiting.h"
26 #include "src/heap/spaces.h"
27 #include "src/heap/store-buffer.h"
28 #include "src/isolate.h"
29 #include "src/lookup.h"
30 #include "src/objects.h"
31 #include "src/property.h"
32 #include "src/prototype.h"
33 #include "src/transitions-inl.h"
34 #include "src/type-feedback-vector-inl.h"
35 #include "src/v8memory.h"
36
37 namespace v8 {
38 namespace internal {
39
PropertyDetails(Smi * smi)40 PropertyDetails::PropertyDetails(Smi* smi) {
41 value_ = smi->value();
42 }
43
44
AsSmi()45 Smi* PropertyDetails::AsSmi() const {
46 // Ensure the upper 2 bits have the same value by sign extending it. This is
47 // necessary to be able to use the 31st bit of the property details.
48 int value = value_ << 1;
49 return Smi::FromInt(value >> 1);
50 }
51
52
AsDeleted()53 PropertyDetails PropertyDetails::AsDeleted() const {
54 Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
55 return PropertyDetails(smi);
56 }
57
58
59 #define TYPE_CHECKER(type, instancetype) \
60 bool Object::Is##type() const { \
61 return Object::IsHeapObject() && \
62 HeapObject::cast(this)->map()->instance_type() == instancetype; \
63 }
64
65
66 #define CAST_ACCESSOR(type) \
67 type* type::cast(Object* object) { \
68 SLOW_DCHECK(object->Is##type()); \
69 return reinterpret_cast<type*>(object); \
70 } \
71 const type* type::cast(const Object* object) { \
72 SLOW_DCHECK(object->Is##type()); \
73 return reinterpret_cast<const type*>(object); \
74 }
75
76
77 #define INT_ACCESSORS(holder, name, offset) \
78 int holder::name() const { return READ_INT_FIELD(this, offset); } \
79 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
80
81
82 #define ACCESSORS(holder, name, type, offset) \
83 type* holder::name() const { return type::cast(READ_FIELD(this, offset)); } \
84 void holder::set_##name(type* value, WriteBarrierMode mode) { \
85 WRITE_FIELD(this, offset, value); \
86 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \
87 }
88
89
90 // Getter that returns a tagged Smi and setter that writes a tagged Smi.
91 #define ACCESSORS_TO_SMI(holder, name, offset) \
92 Smi* holder::name() const { return Smi::cast(READ_FIELD(this, offset)); } \
93 void holder::set_##name(Smi* value, WriteBarrierMode mode) { \
94 WRITE_FIELD(this, offset, value); \
95 }
96
97
98 // Getter that returns a Smi as an int and writes an int as a Smi.
99 #define SMI_ACCESSORS(holder, name, offset) \
100 int holder::name() const { \
101 Object* value = READ_FIELD(this, offset); \
102 return Smi::cast(value)->value(); \
103 } \
104 void holder::set_##name(int value) { \
105 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
106 }
107
108 #define SYNCHRONIZED_SMI_ACCESSORS(holder, name, offset) \
109 int holder::synchronized_##name() const { \
110 Object* value = ACQUIRE_READ_FIELD(this, offset); \
111 return Smi::cast(value)->value(); \
112 } \
113 void holder::synchronized_set_##name(int value) { \
114 RELEASE_WRITE_FIELD(this, offset, Smi::FromInt(value)); \
115 }
116
117 #define NOBARRIER_SMI_ACCESSORS(holder, name, offset) \
118 int holder::nobarrier_##name() const { \
119 Object* value = NOBARRIER_READ_FIELD(this, offset); \
120 return Smi::cast(value)->value(); \
121 } \
122 void holder::nobarrier_set_##name(int value) { \
123 NOBARRIER_WRITE_FIELD(this, offset, Smi::FromInt(value)); \
124 }
125
126 #define BOOL_GETTER(holder, field, name, offset) \
127 bool holder::name() const { \
128 return BooleanBit::get(field(), offset); \
129 } \
130
131
132 #define BOOL_ACCESSORS(holder, field, name, offset) \
133 bool holder::name() const { \
134 return BooleanBit::get(field(), offset); \
135 } \
136 void holder::set_##name(bool value) { \
137 set_##field(BooleanBit::set(field(), offset, value)); \
138 }
139
140
IsFixedArrayBase()141 bool Object::IsFixedArrayBase() const {
142 return IsFixedArray() || IsFixedDoubleArray() || IsConstantPoolArray() ||
143 IsFixedTypedArrayBase() || IsExternalArray();
144 }
145
146
147 // External objects are not extensible, so the map check is enough.
IsExternal()148 bool Object::IsExternal() const {
149 return Object::IsHeapObject() &&
150 HeapObject::cast(this)->map() ==
151 HeapObject::cast(this)->GetHeap()->external_map();
152 }
153
154
IsAccessorInfo()155 bool Object::IsAccessorInfo() const {
156 return IsExecutableAccessorInfo() || IsDeclaredAccessorInfo();
157 }
158
159
IsSmi()160 bool Object::IsSmi() const {
161 return HAS_SMI_TAG(this);
162 }
163
164
IsHeapObject()165 bool Object::IsHeapObject() const {
166 return Internals::HasHeapObjectTag(this);
167 }
168
169
TYPE_CHECKER(HeapNumber,HEAP_NUMBER_TYPE)170 TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
171 TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE)
172 TYPE_CHECKER(Symbol, SYMBOL_TYPE)
173
174
175 bool Object::IsString() const {
176 return Object::IsHeapObject()
177 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
178 }
179
180
IsName()181 bool Object::IsName() const {
182 return IsString() || IsSymbol();
183 }
184
185
IsUniqueName()186 bool Object::IsUniqueName() const {
187 return IsInternalizedString() || IsSymbol();
188 }
189
190
IsSpecObject()191 bool Object::IsSpecObject() const {
192 return Object::IsHeapObject()
193 && HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
194 }
195
196
IsSpecFunction()197 bool Object::IsSpecFunction() const {
198 if (!Object::IsHeapObject()) return false;
199 InstanceType type = HeapObject::cast(this)->map()->instance_type();
200 return type == JS_FUNCTION_TYPE || type == JS_FUNCTION_PROXY_TYPE;
201 }
202
203
IsTemplateInfo()204 bool Object::IsTemplateInfo() const {
205 return IsObjectTemplateInfo() || IsFunctionTemplateInfo();
206 }
207
208
IsInternalizedString()209 bool Object::IsInternalizedString() const {
210 if (!this->IsHeapObject()) return false;
211 uint32_t type = HeapObject::cast(this)->map()->instance_type();
212 STATIC_ASSERT(kNotInternalizedTag != 0);
213 return (type & (kIsNotStringMask | kIsNotInternalizedMask)) ==
214 (kStringTag | kInternalizedTag);
215 }
216
217
IsConsString()218 bool Object::IsConsString() const {
219 if (!IsString()) return false;
220 return StringShape(String::cast(this)).IsCons();
221 }
222
223
IsSlicedString()224 bool Object::IsSlicedString() const {
225 if (!IsString()) return false;
226 return StringShape(String::cast(this)).IsSliced();
227 }
228
229
IsSeqString()230 bool Object::IsSeqString() const {
231 if (!IsString()) return false;
232 return StringShape(String::cast(this)).IsSequential();
233 }
234
235
IsSeqOneByteString()236 bool Object::IsSeqOneByteString() const {
237 if (!IsString()) return false;
238 return StringShape(String::cast(this)).IsSequential() &&
239 String::cast(this)->IsOneByteRepresentation();
240 }
241
242
IsSeqTwoByteString()243 bool Object::IsSeqTwoByteString() const {
244 if (!IsString()) return false;
245 return StringShape(String::cast(this)).IsSequential() &&
246 String::cast(this)->IsTwoByteRepresentation();
247 }
248
249
IsExternalString()250 bool Object::IsExternalString() const {
251 if (!IsString()) return false;
252 return StringShape(String::cast(this)).IsExternal();
253 }
254
255
IsExternalOneByteString()256 bool Object::IsExternalOneByteString() const {
257 if (!IsString()) return false;
258 return StringShape(String::cast(this)).IsExternal() &&
259 String::cast(this)->IsOneByteRepresentation();
260 }
261
262
IsExternalTwoByteString()263 bool Object::IsExternalTwoByteString() const {
264 if (!IsString()) return false;
265 return StringShape(String::cast(this)).IsExternal() &&
266 String::cast(this)->IsTwoByteRepresentation();
267 }
268
269
HasValidElements()270 bool Object::HasValidElements() {
271 // Dictionary is covered under FixedArray.
272 return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray() ||
273 IsFixedTypedArrayBase();
274 }
275
276
NewStorageFor(Isolate * isolate,Handle<Object> object,Representation representation)277 Handle<Object> Object::NewStorageFor(Isolate* isolate,
278 Handle<Object> object,
279 Representation representation) {
280 if (representation.IsSmi() && object->IsUninitialized()) {
281 return handle(Smi::FromInt(0), isolate);
282 }
283 if (!representation.IsDouble()) return object;
284 double value;
285 if (object->IsUninitialized()) {
286 value = 0;
287 } else if (object->IsMutableHeapNumber()) {
288 value = HeapNumber::cast(*object)->value();
289 } else {
290 value = object->Number();
291 }
292 return isolate->factory()->NewHeapNumber(value, MUTABLE);
293 }
294
295
WrapForRead(Isolate * isolate,Handle<Object> object,Representation representation)296 Handle<Object> Object::WrapForRead(Isolate* isolate,
297 Handle<Object> object,
298 Representation representation) {
299 DCHECK(!object->IsUninitialized());
300 if (!representation.IsDouble()) {
301 DCHECK(object->FitsRepresentation(representation));
302 return object;
303 }
304 return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value());
305 }
306
307
StringShape(const String * str)308 StringShape::StringShape(const String* str)
309 : type_(str->map()->instance_type()) {
310 set_valid();
311 DCHECK((type_ & kIsNotStringMask) == kStringTag);
312 }
313
314
StringShape(Map * map)315 StringShape::StringShape(Map* map)
316 : type_(map->instance_type()) {
317 set_valid();
318 DCHECK((type_ & kIsNotStringMask) == kStringTag);
319 }
320
321
StringShape(InstanceType t)322 StringShape::StringShape(InstanceType t)
323 : type_(static_cast<uint32_t>(t)) {
324 set_valid();
325 DCHECK((type_ & kIsNotStringMask) == kStringTag);
326 }
327
328
IsInternalized()329 bool StringShape::IsInternalized() {
330 DCHECK(valid());
331 STATIC_ASSERT(kNotInternalizedTag != 0);
332 return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) ==
333 (kStringTag | kInternalizedTag);
334 }
335
336
IsOneByteRepresentation()337 bool String::IsOneByteRepresentation() const {
338 uint32_t type = map()->instance_type();
339 return (type & kStringEncodingMask) == kOneByteStringTag;
340 }
341
342
IsTwoByteRepresentation()343 bool String::IsTwoByteRepresentation() const {
344 uint32_t type = map()->instance_type();
345 return (type & kStringEncodingMask) == kTwoByteStringTag;
346 }
347
348
IsOneByteRepresentationUnderneath()349 bool String::IsOneByteRepresentationUnderneath() {
350 uint32_t type = map()->instance_type();
351 STATIC_ASSERT(kIsIndirectStringTag != 0);
352 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
353 DCHECK(IsFlat());
354 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
355 case kOneByteStringTag:
356 return true;
357 case kTwoByteStringTag:
358 return false;
359 default: // Cons or sliced string. Need to go deeper.
360 return GetUnderlying()->IsOneByteRepresentation();
361 }
362 }
363
364
IsTwoByteRepresentationUnderneath()365 bool String::IsTwoByteRepresentationUnderneath() {
366 uint32_t type = map()->instance_type();
367 STATIC_ASSERT(kIsIndirectStringTag != 0);
368 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
369 DCHECK(IsFlat());
370 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
371 case kOneByteStringTag:
372 return false;
373 case kTwoByteStringTag:
374 return true;
375 default: // Cons or sliced string. Need to go deeper.
376 return GetUnderlying()->IsTwoByteRepresentation();
377 }
378 }
379
380
HasOnlyOneByteChars()381 bool String::HasOnlyOneByteChars() {
382 uint32_t type = map()->instance_type();
383 return (type & kOneByteDataHintMask) == kOneByteDataHintTag ||
384 IsOneByteRepresentation();
385 }
386
387
IsCons()388 bool StringShape::IsCons() {
389 return (type_ & kStringRepresentationMask) == kConsStringTag;
390 }
391
392
IsSliced()393 bool StringShape::IsSliced() {
394 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
395 }
396
397
IsIndirect()398 bool StringShape::IsIndirect() {
399 return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
400 }
401
402
IsExternal()403 bool StringShape::IsExternal() {
404 return (type_ & kStringRepresentationMask) == kExternalStringTag;
405 }
406
407
IsSequential()408 bool StringShape::IsSequential() {
409 return (type_ & kStringRepresentationMask) == kSeqStringTag;
410 }
411
412
representation_tag()413 StringRepresentationTag StringShape::representation_tag() {
414 uint32_t tag = (type_ & kStringRepresentationMask);
415 return static_cast<StringRepresentationTag>(tag);
416 }
417
418
encoding_tag()419 uint32_t StringShape::encoding_tag() {
420 return type_ & kStringEncodingMask;
421 }
422
423
full_representation_tag()424 uint32_t StringShape::full_representation_tag() {
425 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
426 }
427
428
429 STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) ==
430 Internals::kFullStringRepresentationMask);
431
432 STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) ==
433 Internals::kStringEncodingMask);
434
435
IsSequentialOneByte()436 bool StringShape::IsSequentialOneByte() {
437 return full_representation_tag() == (kSeqStringTag | kOneByteStringTag);
438 }
439
440
IsSequentialTwoByte()441 bool StringShape::IsSequentialTwoByte() {
442 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
443 }
444
445
IsExternalOneByte()446 bool StringShape::IsExternalOneByte() {
447 return full_representation_tag() == (kExternalStringTag | kOneByteStringTag);
448 }
449
450
451 STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) ==
452 Internals::kExternalOneByteRepresentationTag);
453
454 STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag);
455
456
IsExternalTwoByte()457 bool StringShape::IsExternalTwoByte() {
458 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
459 }
460
461
462 STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) ==
463 Internals::kExternalTwoByteRepresentationTag);
464
465 STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
466
Get(int index)467 uc32 FlatStringReader::Get(int index) {
468 DCHECK(0 <= index && index <= length_);
469 if (is_one_byte_) {
470 return static_cast<const byte*>(start_)[index];
471 } else {
472 return static_cast<const uc16*>(start_)[index];
473 }
474 }
475
476
AsHandle(Isolate * isolate,HashTableKey * key)477 Handle<Object> StringTableShape::AsHandle(Isolate* isolate, HashTableKey* key) {
478 return key->AsHandle(isolate);
479 }
480
481
AsHandle(Isolate * isolate,HashTableKey * key)482 Handle<Object> MapCacheShape::AsHandle(Isolate* isolate, HashTableKey* key) {
483 return key->AsHandle(isolate);
484 }
485
486
AsHandle(Isolate * isolate,HashTableKey * key)487 Handle<Object> CompilationCacheShape::AsHandle(Isolate* isolate,
488 HashTableKey* key) {
489 return key->AsHandle(isolate);
490 }
491
492
AsHandle(Isolate * isolate,HashTableKey * key)493 Handle<Object> CodeCacheHashTableShape::AsHandle(Isolate* isolate,
494 HashTableKey* key) {
495 return key->AsHandle(isolate);
496 }
497
498 template <typename Char>
499 class SequentialStringKey : public HashTableKey {
500 public:
SequentialStringKey(Vector<const Char> string,uint32_t seed)501 explicit SequentialStringKey(Vector<const Char> string, uint32_t seed)
502 : string_(string), hash_field_(0), seed_(seed) { }
503
Hash()504 virtual uint32_t Hash() OVERRIDE {
505 hash_field_ = StringHasher::HashSequentialString<Char>(string_.start(),
506 string_.length(),
507 seed_);
508
509 uint32_t result = hash_field_ >> String::kHashShift;
510 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
511 return result;
512 }
513
514
HashForObject(Object * other)515 virtual uint32_t HashForObject(Object* other) OVERRIDE {
516 return String::cast(other)->Hash();
517 }
518
519 Vector<const Char> string_;
520 uint32_t hash_field_;
521 uint32_t seed_;
522 };
523
524
525 class OneByteStringKey : public SequentialStringKey<uint8_t> {
526 public:
OneByteStringKey(Vector<const uint8_t> str,uint32_t seed)527 OneByteStringKey(Vector<const uint8_t> str, uint32_t seed)
528 : SequentialStringKey<uint8_t>(str, seed) { }
529
IsMatch(Object * string)530 virtual bool IsMatch(Object* string) OVERRIDE {
531 return String::cast(string)->IsOneByteEqualTo(string_);
532 }
533
534 virtual Handle<Object> AsHandle(Isolate* isolate) OVERRIDE;
535 };
536
537
538 class SeqOneByteSubStringKey : public HashTableKey {
539 public:
SeqOneByteSubStringKey(Handle<SeqOneByteString> string,int from,int length)540 SeqOneByteSubStringKey(Handle<SeqOneByteString> string, int from, int length)
541 : string_(string), from_(from), length_(length) {
542 DCHECK(string_->IsSeqOneByteString());
543 }
544
Hash()545 virtual uint32_t Hash() OVERRIDE {
546 DCHECK(length_ >= 0);
547 DCHECK(from_ + length_ <= string_->length());
548 const uint8_t* chars = string_->GetChars() + from_;
549 hash_field_ = StringHasher::HashSequentialString(
550 chars, length_, string_->GetHeap()->HashSeed());
551 uint32_t result = hash_field_ >> String::kHashShift;
552 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
553 return result;
554 }
555
HashForObject(Object * other)556 virtual uint32_t HashForObject(Object* other) OVERRIDE {
557 return String::cast(other)->Hash();
558 }
559
560 virtual bool IsMatch(Object* string) OVERRIDE;
561 virtual Handle<Object> AsHandle(Isolate* isolate) OVERRIDE;
562
563 private:
564 Handle<SeqOneByteString> string_;
565 int from_;
566 int length_;
567 uint32_t hash_field_;
568 };
569
570
571 class TwoByteStringKey : public SequentialStringKey<uc16> {
572 public:
TwoByteStringKey(Vector<const uc16> str,uint32_t seed)573 explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed)
574 : SequentialStringKey<uc16>(str, seed) { }
575
IsMatch(Object * string)576 virtual bool IsMatch(Object* string) OVERRIDE {
577 return String::cast(string)->IsTwoByteEqualTo(string_);
578 }
579
580 virtual Handle<Object> AsHandle(Isolate* isolate) OVERRIDE;
581 };
582
583
584 // Utf8StringKey carries a vector of chars as key.
585 class Utf8StringKey : public HashTableKey {
586 public:
Utf8StringKey(Vector<const char> string,uint32_t seed)587 explicit Utf8StringKey(Vector<const char> string, uint32_t seed)
588 : string_(string), hash_field_(0), seed_(seed) { }
589
IsMatch(Object * string)590 virtual bool IsMatch(Object* string) OVERRIDE {
591 return String::cast(string)->IsUtf8EqualTo(string_);
592 }
593
Hash()594 virtual uint32_t Hash() OVERRIDE {
595 if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
596 hash_field_ = StringHasher::ComputeUtf8Hash(string_, seed_, &chars_);
597 uint32_t result = hash_field_ >> String::kHashShift;
598 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
599 return result;
600 }
601
HashForObject(Object * other)602 virtual uint32_t HashForObject(Object* other) OVERRIDE {
603 return String::cast(other)->Hash();
604 }
605
AsHandle(Isolate * isolate)606 virtual Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
607 if (hash_field_ == 0) Hash();
608 return isolate->factory()->NewInternalizedStringFromUtf8(
609 string_, chars_, hash_field_);
610 }
611
612 Vector<const char> string_;
613 uint32_t hash_field_;
614 int chars_; // Caches the number of characters when computing the hash code.
615 uint32_t seed_;
616 };
617
618
IsNumber()619 bool Object::IsNumber() const {
620 return IsSmi() || IsHeapNumber();
621 }
622
623
TYPE_CHECKER(ByteArray,BYTE_ARRAY_TYPE)624 TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
625 TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
626
627
628 bool Object::IsFiller() const {
629 if (!Object::IsHeapObject()) return false;
630 InstanceType instance_type = HeapObject::cast(this)->map()->instance_type();
631 return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
632 }
633
634
IsExternalArray()635 bool Object::IsExternalArray() const {
636 if (!Object::IsHeapObject())
637 return false;
638 InstanceType instance_type =
639 HeapObject::cast(this)->map()->instance_type();
640 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
641 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
642 }
643
644
645 #define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size) \
646 TYPE_CHECKER(External##Type##Array, EXTERNAL_##TYPE##_ARRAY_TYPE) \
647 TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE)
648
TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER)649 TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER)
650 #undef TYPED_ARRAY_TYPE_CHECKER
651
652
653 bool Object::IsFixedTypedArrayBase() const {
654 if (!Object::IsHeapObject()) return false;
655
656 InstanceType instance_type =
657 HeapObject::cast(this)->map()->instance_type();
658 return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
659 instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE);
660 }
661
662
IsJSReceiver()663 bool Object::IsJSReceiver() const {
664 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
665 return IsHeapObject() &&
666 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
667 }
668
669
IsJSObject()670 bool Object::IsJSObject() const {
671 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
672 return IsHeapObject() &&
673 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
674 }
675
676
IsJSProxy()677 bool Object::IsJSProxy() const {
678 if (!Object::IsHeapObject()) return false;
679 return HeapObject::cast(this)->map()->IsJSProxyMap();
680 }
681
682
TYPE_CHECKER(JSFunctionProxy,JS_FUNCTION_PROXY_TYPE)683 TYPE_CHECKER(JSFunctionProxy, JS_FUNCTION_PROXY_TYPE)
684 TYPE_CHECKER(JSSet, JS_SET_TYPE)
685 TYPE_CHECKER(JSMap, JS_MAP_TYPE)
686 TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE)
687 TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE)
688 TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
689 TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE)
690 TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
691 TYPE_CHECKER(Map, MAP_TYPE)
692 TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE)
693 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
694 TYPE_CHECKER(ConstantPoolArray, CONSTANT_POOL_ARRAY_TYPE)
695
696
697 bool Object::IsJSWeakCollection() const {
698 return IsJSWeakMap() || IsJSWeakSet();
699 }
700
701
IsDescriptorArray()702 bool Object::IsDescriptorArray() const {
703 return IsFixedArray();
704 }
705
706
IsTransitionArray()707 bool Object::IsTransitionArray() const {
708 return IsFixedArray();
709 }
710
711
IsTypeFeedbackVector()712 bool Object::IsTypeFeedbackVector() const { return IsFixedArray(); }
713
714
IsDeoptimizationInputData()715 bool Object::IsDeoptimizationInputData() const {
716 // Must be a fixed array.
717 if (!IsFixedArray()) return false;
718
719 // There's no sure way to detect the difference between a fixed array and
720 // a deoptimization data array. Since this is used for asserts we can
721 // check that the length is zero or else the fixed size plus a multiple of
722 // the entry size.
723 int length = FixedArray::cast(this)->length();
724 if (length == 0) return true;
725
726 length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
727 return length >= 0 && length % DeoptimizationInputData::kDeoptEntrySize == 0;
728 }
729
730
IsDeoptimizationOutputData()731 bool Object::IsDeoptimizationOutputData() const {
732 if (!IsFixedArray()) return false;
733 // There's actually no way to see the difference between a fixed array and
734 // a deoptimization data array. Since this is used for asserts we can check
735 // that the length is plausible though.
736 if (FixedArray::cast(this)->length() % 2 != 0) return false;
737 return true;
738 }
739
740
IsDependentCode()741 bool Object::IsDependentCode() const {
742 if (!IsFixedArray()) return false;
743 // There's actually no way to see the difference between a fixed array and
744 // a dependent codes array.
745 return true;
746 }
747
748
IsContext()749 bool Object::IsContext() const {
750 if (!Object::IsHeapObject()) return false;
751 Map* map = HeapObject::cast(this)->map();
752 Heap* heap = map->GetHeap();
753 return (map == heap->function_context_map() ||
754 map == heap->catch_context_map() ||
755 map == heap->with_context_map() ||
756 map == heap->native_context_map() ||
757 map == heap->block_context_map() ||
758 map == heap->module_context_map() ||
759 map == heap->global_context_map());
760 }
761
762
IsNativeContext()763 bool Object::IsNativeContext() const {
764 return Object::IsHeapObject() &&
765 HeapObject::cast(this)->map() ==
766 HeapObject::cast(this)->GetHeap()->native_context_map();
767 }
768
769
IsScopeInfo()770 bool Object::IsScopeInfo() const {
771 return Object::IsHeapObject() &&
772 HeapObject::cast(this)->map() ==
773 HeapObject::cast(this)->GetHeap()->scope_info_map();
774 }
775
776
TYPE_CHECKER(JSFunction,JS_FUNCTION_TYPE)777 TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
778
779
780 template <> inline bool Is<JSFunction>(Object* obj) {
781 return obj->IsJSFunction();
782 }
783
784
TYPE_CHECKER(Code,CODE_TYPE)785 TYPE_CHECKER(Code, CODE_TYPE)
786 TYPE_CHECKER(Oddball, ODDBALL_TYPE)
787 TYPE_CHECKER(Cell, CELL_TYPE)
788 TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE)
789 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
790 TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
791 TYPE_CHECKER(JSModule, JS_MODULE_TYPE)
792 TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
793 TYPE_CHECKER(JSDate, JS_DATE_TYPE)
794 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
795
796
797 bool Object::IsStringWrapper() const {
798 return IsJSValue() && JSValue::cast(this)->value()->IsString();
799 }
800
801
TYPE_CHECKER(Foreign,FOREIGN_TYPE)802 TYPE_CHECKER(Foreign, FOREIGN_TYPE)
803
804
805 bool Object::IsBoolean() const {
806 return IsOddball() &&
807 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
808 }
809
810
TYPE_CHECKER(JSArray,JS_ARRAY_TYPE)811 TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
812 TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE)
813 TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE)
814 TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE)
815
816
817 bool Object::IsJSArrayBufferView() const {
818 return IsJSDataView() || IsJSTypedArray();
819 }
820
821
TYPE_CHECKER(JSRegExp,JS_REGEXP_TYPE)822 TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
823
824
825 template <> inline bool Is<JSArray>(Object* obj) {
826 return obj->IsJSArray();
827 }
828
829
IsHashTable()830 bool Object::IsHashTable() const {
831 return Object::IsHeapObject() &&
832 HeapObject::cast(this)->map() ==
833 HeapObject::cast(this)->GetHeap()->hash_table_map();
834 }
835
836
IsWeakHashTable()837 bool Object::IsWeakHashTable() const {
838 return IsHashTable();
839 }
840
841
IsDictionary()842 bool Object::IsDictionary() const {
843 return IsHashTable() &&
844 this != HeapObject::cast(this)->GetHeap()->string_table();
845 }
846
847
IsNameDictionary()848 bool Object::IsNameDictionary() const {
849 return IsDictionary();
850 }
851
852
IsSeededNumberDictionary()853 bool Object::IsSeededNumberDictionary() const {
854 return IsDictionary();
855 }
856
857
IsUnseededNumberDictionary()858 bool Object::IsUnseededNumberDictionary() const {
859 return IsDictionary();
860 }
861
862
IsStringTable()863 bool Object::IsStringTable() const {
864 return IsHashTable();
865 }
866
867
IsJSFunctionResultCache()868 bool Object::IsJSFunctionResultCache() const {
869 if (!IsFixedArray()) return false;
870 const FixedArray* self = FixedArray::cast(this);
871 int length = self->length();
872 if (length < JSFunctionResultCache::kEntriesIndex) return false;
873 if ((length - JSFunctionResultCache::kEntriesIndex)
874 % JSFunctionResultCache::kEntrySize != 0) {
875 return false;
876 }
877 #ifdef VERIFY_HEAP
878 if (FLAG_verify_heap) {
879 // TODO(svenpanne) We use const_cast here and below to break our dependency
880 // cycle between the predicates and the verifiers. This can be removed when
881 // the verifiers are const-correct, too.
882 reinterpret_cast<JSFunctionResultCache*>(const_cast<Object*>(this))->
883 JSFunctionResultCacheVerify();
884 }
885 #endif
886 return true;
887 }
888
889
IsNormalizedMapCache()890 bool Object::IsNormalizedMapCache() const {
891 return NormalizedMapCache::IsNormalizedMapCache(this);
892 }
893
894
GetIndex(Handle<Map> map)895 int NormalizedMapCache::GetIndex(Handle<Map> map) {
896 return map->Hash() % NormalizedMapCache::kEntries;
897 }
898
899
IsNormalizedMapCache(const Object * obj)900 bool NormalizedMapCache::IsNormalizedMapCache(const Object* obj) {
901 if (!obj->IsFixedArray()) return false;
902 if (FixedArray::cast(obj)->length() != NormalizedMapCache::kEntries) {
903 return false;
904 }
905 #ifdef VERIFY_HEAP
906 if (FLAG_verify_heap) {
907 reinterpret_cast<NormalizedMapCache*>(const_cast<Object*>(obj))->
908 NormalizedMapCacheVerify();
909 }
910 #endif
911 return true;
912 }
913
914
IsCompilationCacheTable()915 bool Object::IsCompilationCacheTable() const {
916 return IsHashTable();
917 }
918
919
IsCodeCacheHashTable()920 bool Object::IsCodeCacheHashTable() const {
921 return IsHashTable();
922 }
923
924
IsPolymorphicCodeCacheHashTable()925 bool Object::IsPolymorphicCodeCacheHashTable() const {
926 return IsHashTable();
927 }
928
929
IsMapCache()930 bool Object::IsMapCache() const {
931 return IsHashTable();
932 }
933
934
IsObjectHashTable()935 bool Object::IsObjectHashTable() const {
936 return IsHashTable();
937 }
938
939
IsOrderedHashTable()940 bool Object::IsOrderedHashTable() const {
941 return IsHeapObject() &&
942 HeapObject::cast(this)->map() ==
943 HeapObject::cast(this)->GetHeap()->ordered_hash_table_map();
944 }
945
946
IsOrderedHashSet()947 bool Object::IsOrderedHashSet() const {
948 return IsOrderedHashTable();
949 }
950
951
IsOrderedHashMap()952 bool Object::IsOrderedHashMap() const {
953 return IsOrderedHashTable();
954 }
955
956
IsPrimitive()957 bool Object::IsPrimitive() const {
958 return IsOddball() || IsNumber() || IsString();
959 }
960
961
IsJSGlobalProxy()962 bool Object::IsJSGlobalProxy() const {
963 bool result = IsHeapObject() &&
964 (HeapObject::cast(this)->map()->instance_type() ==
965 JS_GLOBAL_PROXY_TYPE);
966 DCHECK(!result ||
967 HeapObject::cast(this)->map()->is_access_check_needed());
968 return result;
969 }
970
971
IsGlobalObject()972 bool Object::IsGlobalObject() const {
973 if (!IsHeapObject()) return false;
974
975 InstanceType type = HeapObject::cast(this)->map()->instance_type();
976 return type == JS_GLOBAL_OBJECT_TYPE ||
977 type == JS_BUILTINS_OBJECT_TYPE;
978 }
979
980
TYPE_CHECKER(JSGlobalObject,JS_GLOBAL_OBJECT_TYPE)981 TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
982 TYPE_CHECKER(JSBuiltinsObject, JS_BUILTINS_OBJECT_TYPE)
983
984
985 bool Object::IsUndetectableObject() const {
986 return IsHeapObject()
987 && HeapObject::cast(this)->map()->is_undetectable();
988 }
989
990
IsAccessCheckNeeded()991 bool Object::IsAccessCheckNeeded() const {
992 if (!IsHeapObject()) return false;
993 if (IsJSGlobalProxy()) {
994 const JSGlobalProxy* proxy = JSGlobalProxy::cast(this);
995 GlobalObject* global = proxy->GetIsolate()->context()->global_object();
996 return proxy->IsDetachedFrom(global);
997 }
998 return HeapObject::cast(this)->map()->is_access_check_needed();
999 }
1000
1001
IsStruct()1002 bool Object::IsStruct() const {
1003 if (!IsHeapObject()) return false;
1004 switch (HeapObject::cast(this)->map()->instance_type()) {
1005 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
1006 STRUCT_LIST(MAKE_STRUCT_CASE)
1007 #undef MAKE_STRUCT_CASE
1008 default: return false;
1009 }
1010 }
1011
1012
1013 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
1014 bool Object::Is##Name() const { \
1015 return Object::IsHeapObject() \
1016 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
1017 }
STRUCT_LIST(MAKE_STRUCT_PREDICATE)1018 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
1019 #undef MAKE_STRUCT_PREDICATE
1020
1021
1022 bool Object::IsUndefined() const {
1023 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
1024 }
1025
1026
IsNull()1027 bool Object::IsNull() const {
1028 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
1029 }
1030
1031
IsTheHole()1032 bool Object::IsTheHole() const {
1033 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
1034 }
1035
1036
IsException()1037 bool Object::IsException() const {
1038 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kException;
1039 }
1040
1041
IsUninitialized()1042 bool Object::IsUninitialized() const {
1043 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUninitialized;
1044 }
1045
1046
IsTrue()1047 bool Object::IsTrue() const {
1048 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
1049 }
1050
1051
IsFalse()1052 bool Object::IsFalse() const {
1053 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
1054 }
1055
1056
IsArgumentsMarker()1057 bool Object::IsArgumentsMarker() const {
1058 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
1059 }
1060
1061
Number()1062 double Object::Number() {
1063 DCHECK(IsNumber());
1064 return IsSmi()
1065 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
1066 : reinterpret_cast<HeapNumber*>(this)->value();
1067 }
1068
1069
IsNaN()1070 bool Object::IsNaN() const {
1071 return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value());
1072 }
1073
1074
IsMinusZero()1075 bool Object::IsMinusZero() const {
1076 return this->IsHeapNumber() &&
1077 i::IsMinusZero(HeapNumber::cast(this)->value());
1078 }
1079
1080
ToSmi(Isolate * isolate,Handle<Object> object)1081 MaybeHandle<Smi> Object::ToSmi(Isolate* isolate, Handle<Object> object) {
1082 if (object->IsSmi()) return Handle<Smi>::cast(object);
1083 if (object->IsHeapNumber()) {
1084 double value = Handle<HeapNumber>::cast(object)->value();
1085 int int_value = FastD2I(value);
1086 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
1087 return handle(Smi::FromInt(int_value), isolate);
1088 }
1089 }
1090 return Handle<Smi>();
1091 }
1092
1093
ToObject(Isolate * isolate,Handle<Object> object)1094 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
1095 Handle<Object> object) {
1096 return ToObject(
1097 isolate, object, handle(isolate->context()->native_context(), isolate));
1098 }
1099
1100
HasSpecificClassOf(String * name)1101 bool Object::HasSpecificClassOf(String* name) {
1102 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
1103 }
1104
1105
GetProperty(Handle<Object> object,Handle<Name> name)1106 MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
1107 Handle<Name> name) {
1108 LookupIterator it(object, name);
1109 return GetProperty(&it);
1110 }
1111
1112
GetElement(Isolate * isolate,Handle<Object> object,uint32_t index)1113 MaybeHandle<Object> Object::GetElement(Isolate* isolate,
1114 Handle<Object> object,
1115 uint32_t index) {
1116 // GetElement can trigger a getter which can cause allocation.
1117 // This was not always the case. This DCHECK is here to catch
1118 // leftover incorrect uses.
1119 DCHECK(AllowHeapAllocation::IsAllowed());
1120 return Object::GetElementWithReceiver(isolate, object, object, index);
1121 }
1122
1123
GetPropertyOrElement(Handle<Object> object,Handle<Name> name)1124 MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object,
1125 Handle<Name> name) {
1126 uint32_t index;
1127 Isolate* isolate = name->GetIsolate();
1128 if (name->AsArrayIndex(&index)) return GetElement(isolate, object, index);
1129 return GetProperty(object, name);
1130 }
1131
1132
GetProperty(Isolate * isolate,Handle<Object> object,const char * name)1133 MaybeHandle<Object> Object::GetProperty(Isolate* isolate,
1134 Handle<Object> object,
1135 const char* name) {
1136 Handle<String> str = isolate->factory()->InternalizeUtf8String(name);
1137 DCHECK(!str.is_null());
1138 #ifdef DEBUG
1139 uint32_t index; // Assert that the name is not an array index.
1140 DCHECK(!str->AsArrayIndex(&index));
1141 #endif // DEBUG
1142 return GetProperty(object, str);
1143 }
1144
1145
GetElementWithHandler(Handle<JSProxy> proxy,Handle<Object> receiver,uint32_t index)1146 MaybeHandle<Object> JSProxy::GetElementWithHandler(Handle<JSProxy> proxy,
1147 Handle<Object> receiver,
1148 uint32_t index) {
1149 return GetPropertyWithHandler(
1150 proxy, receiver, proxy->GetIsolate()->factory()->Uint32ToString(index));
1151 }
1152
1153
SetElementWithHandler(Handle<JSProxy> proxy,Handle<JSReceiver> receiver,uint32_t index,Handle<Object> value,StrictMode strict_mode)1154 MaybeHandle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
1155 Handle<JSReceiver> receiver,
1156 uint32_t index,
1157 Handle<Object> value,
1158 StrictMode strict_mode) {
1159 Isolate* isolate = proxy->GetIsolate();
1160 Handle<String> name = isolate->factory()->Uint32ToString(index);
1161 return SetPropertyWithHandler(proxy, receiver, name, value, strict_mode);
1162 }
1163
1164
HasElementWithHandler(Handle<JSProxy> proxy,uint32_t index)1165 Maybe<bool> JSProxy::HasElementWithHandler(Handle<JSProxy> proxy,
1166 uint32_t index) {
1167 Isolate* isolate = proxy->GetIsolate();
1168 Handle<String> name = isolate->factory()->Uint32ToString(index);
1169 return HasPropertyWithHandler(proxy, name);
1170 }
1171
1172
1173 #define FIELD_ADDR(p, offset) \
1174 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
1175
1176 #define FIELD_ADDR_CONST(p, offset) \
1177 (reinterpret_cast<const byte*>(p) + offset - kHeapObjectTag)
1178
1179 #define READ_FIELD(p, offset) \
1180 (*reinterpret_cast<Object* const*>(FIELD_ADDR_CONST(p, offset)))
1181
1182 #define ACQUIRE_READ_FIELD(p, offset) \
1183 reinterpret_cast<Object*>(base::Acquire_Load( \
1184 reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset))))
1185
1186 #define NOBARRIER_READ_FIELD(p, offset) \
1187 reinterpret_cast<Object*>(base::NoBarrier_Load( \
1188 reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset))))
1189
1190 #define WRITE_FIELD(p, offset, value) \
1191 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
1192
1193 #define RELEASE_WRITE_FIELD(p, offset, value) \
1194 base::Release_Store( \
1195 reinterpret_cast<base::AtomicWord*>(FIELD_ADDR(p, offset)), \
1196 reinterpret_cast<base::AtomicWord>(value));
1197
1198 #define NOBARRIER_WRITE_FIELD(p, offset, value) \
1199 base::NoBarrier_Store( \
1200 reinterpret_cast<base::AtomicWord*>(FIELD_ADDR(p, offset)), \
1201 reinterpret_cast<base::AtomicWord>(value));
1202
1203 #define WRITE_BARRIER(heap, object, offset, value) \
1204 heap->incremental_marking()->RecordWrite( \
1205 object, HeapObject::RawField(object, offset), value); \
1206 if (heap->InNewSpace(value)) { \
1207 heap->RecordWrite(object->address(), offset); \
1208 }
1209
1210 #define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \
1211 if (mode == UPDATE_WRITE_BARRIER) { \
1212 heap->incremental_marking()->RecordWrite( \
1213 object, HeapObject::RawField(object, offset), value); \
1214 if (heap->InNewSpace(value)) { \
1215 heap->RecordWrite(object->address(), offset); \
1216 } \
1217 }
1218
1219 #ifndef V8_TARGET_ARCH_MIPS
1220 #define READ_DOUBLE_FIELD(p, offset) \
1221 (*reinterpret_cast<const double*>(FIELD_ADDR_CONST(p, offset)))
1222 #else // V8_TARGET_ARCH_MIPS
1223 // Prevent gcc from using load-double (mips ldc1) on (possibly)
1224 // non-64-bit aligned HeapNumber::value.
read_double_field(const void * p,int offset)1225 static inline double read_double_field(const void* p, int offset) {
1226 union conversion {
1227 double d;
1228 uint32_t u[2];
1229 } c;
1230 c.u[0] = (*reinterpret_cast<const uint32_t*>(
1231 FIELD_ADDR_CONST(p, offset)));
1232 c.u[1] = (*reinterpret_cast<const uint32_t*>(
1233 FIELD_ADDR_CONST(p, offset + 4)));
1234 return c.d;
1235 }
1236 #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset)
1237 #endif // V8_TARGET_ARCH_MIPS
1238
1239 #ifndef V8_TARGET_ARCH_MIPS
1240 #define WRITE_DOUBLE_FIELD(p, offset, value) \
1241 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
1242 #else // V8_TARGET_ARCH_MIPS
1243 // Prevent gcc from using store-double (mips sdc1) on (possibly)
1244 // non-64-bit aligned HeapNumber::value.
write_double_field(void * p,int offset,double value)1245 static inline void write_double_field(void* p, int offset,
1246 double value) {
1247 union conversion {
1248 double d;
1249 uint32_t u[2];
1250 } c;
1251 c.d = value;
1252 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0];
1253 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1];
1254 }
1255 #define WRITE_DOUBLE_FIELD(p, offset, value) \
1256 write_double_field(p, offset, value)
1257 #endif // V8_TARGET_ARCH_MIPS
1258
1259
1260 #define READ_INT_FIELD(p, offset) \
1261 (*reinterpret_cast<const int*>(FIELD_ADDR_CONST(p, offset)))
1262
1263 #define WRITE_INT_FIELD(p, offset, value) \
1264 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
1265
1266 #define READ_INTPTR_FIELD(p, offset) \
1267 (*reinterpret_cast<const intptr_t*>(FIELD_ADDR_CONST(p, offset)))
1268
1269 #define WRITE_INTPTR_FIELD(p, offset, value) \
1270 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
1271
1272 #define READ_UINT32_FIELD(p, offset) \
1273 (*reinterpret_cast<const uint32_t*>(FIELD_ADDR_CONST(p, offset)))
1274
1275 #define WRITE_UINT32_FIELD(p, offset, value) \
1276 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
1277
1278 #define READ_INT32_FIELD(p, offset) \
1279 (*reinterpret_cast<const int32_t*>(FIELD_ADDR_CONST(p, offset)))
1280
1281 #define WRITE_INT32_FIELD(p, offset, value) \
1282 (*reinterpret_cast<int32_t*>(FIELD_ADDR(p, offset)) = value)
1283
1284 #define READ_INT64_FIELD(p, offset) \
1285 (*reinterpret_cast<const int64_t*>(FIELD_ADDR_CONST(p, offset)))
1286
1287 #define WRITE_INT64_FIELD(p, offset, value) \
1288 (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)) = value)
1289
1290 #define READ_SHORT_FIELD(p, offset) \
1291 (*reinterpret_cast<const uint16_t*>(FIELD_ADDR_CONST(p, offset)))
1292
1293 #define WRITE_SHORT_FIELD(p, offset, value) \
1294 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
1295
1296 #define READ_BYTE_FIELD(p, offset) \
1297 (*reinterpret_cast<const byte*>(FIELD_ADDR_CONST(p, offset)))
1298
1299 #define NOBARRIER_READ_BYTE_FIELD(p, offset) \
1300 static_cast<byte>(base::NoBarrier_Load( \
1301 reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset))))
1302
1303 #define WRITE_BYTE_FIELD(p, offset, value) \
1304 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
1305
1306 #define NOBARRIER_WRITE_BYTE_FIELD(p, offset, value) \
1307 base::NoBarrier_Store( \
1308 reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset)), \
1309 static_cast<base::Atomic8>(value));
1310
RawField(HeapObject * obj,int byte_offset)1311 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
1312 return reinterpret_cast<Object**>(FIELD_ADDR(obj, byte_offset));
1313 }
1314
1315
value()1316 int Smi::value() const {
1317 return Internals::SmiValue(this);
1318 }
1319
1320
FromInt(int value)1321 Smi* Smi::FromInt(int value) {
1322 DCHECK(Smi::IsValid(value));
1323 return reinterpret_cast<Smi*>(Internals::IntToSmi(value));
1324 }
1325
1326
FromIntptr(intptr_t value)1327 Smi* Smi::FromIntptr(intptr_t value) {
1328 DCHECK(Smi::IsValid(value));
1329 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
1330 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
1331 }
1332
1333
IsValid(intptr_t value)1334 bool Smi::IsValid(intptr_t value) {
1335 bool result = Internals::IsValidSmi(value);
1336 DCHECK_EQ(result, value >= kMinValue && value <= kMaxValue);
1337 return result;
1338 }
1339
1340
FromMap(const Map * map)1341 MapWord MapWord::FromMap(const Map* map) {
1342 return MapWord(reinterpret_cast<uintptr_t>(map));
1343 }
1344
1345
ToMap()1346 Map* MapWord::ToMap() {
1347 return reinterpret_cast<Map*>(value_);
1348 }
1349
1350
IsForwardingAddress()1351 bool MapWord::IsForwardingAddress() {
1352 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
1353 }
1354
1355
FromForwardingAddress(HeapObject * object)1356 MapWord MapWord::FromForwardingAddress(HeapObject* object) {
1357 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
1358 return MapWord(reinterpret_cast<uintptr_t>(raw));
1359 }
1360
1361
ToForwardingAddress()1362 HeapObject* MapWord::ToForwardingAddress() {
1363 DCHECK(IsForwardingAddress());
1364 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
1365 }
1366
1367
1368 #ifdef VERIFY_HEAP
VerifyObjectField(int offset)1369 void HeapObject::VerifyObjectField(int offset) {
1370 VerifyPointer(READ_FIELD(this, offset));
1371 }
1372
VerifySmiField(int offset)1373 void HeapObject::VerifySmiField(int offset) {
1374 CHECK(READ_FIELD(this, offset)->IsSmi());
1375 }
1376 #endif
1377
1378
GetHeap()1379 Heap* HeapObject::GetHeap() const {
1380 Heap* heap =
1381 MemoryChunk::FromAddress(reinterpret_cast<const byte*>(this))->heap();
1382 SLOW_DCHECK(heap != NULL);
1383 return heap;
1384 }
1385
1386
GetIsolate()1387 Isolate* HeapObject::GetIsolate() const {
1388 return GetHeap()->isolate();
1389 }
1390
1391
map()1392 Map* HeapObject::map() const {
1393 #ifdef DEBUG
1394 // Clear mark potentially added by PathTracer.
1395 uintptr_t raw_value =
1396 map_word().ToRawValue() & ~static_cast<uintptr_t>(PathTracer::kMarkTag);
1397 return MapWord::FromRawValue(raw_value).ToMap();
1398 #else
1399 return map_word().ToMap();
1400 #endif
1401 }
1402
1403
set_map(Map * value)1404 void HeapObject::set_map(Map* value) {
1405 set_map_word(MapWord::FromMap(value));
1406 if (value != NULL) {
1407 // TODO(1600) We are passing NULL as a slot because maps can never be on
1408 // evacuation candidate.
1409 value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value);
1410 }
1411 }
1412
1413
synchronized_map()1414 Map* HeapObject::synchronized_map() {
1415 return synchronized_map_word().ToMap();
1416 }
1417
1418
synchronized_set_map(Map * value)1419 void HeapObject::synchronized_set_map(Map* value) {
1420 synchronized_set_map_word(MapWord::FromMap(value));
1421 if (value != NULL) {
1422 // TODO(1600) We are passing NULL as a slot because maps can never be on
1423 // evacuation candidate.
1424 value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value);
1425 }
1426 }
1427
1428
synchronized_set_map_no_write_barrier(Map * value)1429 void HeapObject::synchronized_set_map_no_write_barrier(Map* value) {
1430 synchronized_set_map_word(MapWord::FromMap(value));
1431 }
1432
1433
1434 // Unsafe accessor omitting write barrier.
set_map_no_write_barrier(Map * value)1435 void HeapObject::set_map_no_write_barrier(Map* value) {
1436 set_map_word(MapWord::FromMap(value));
1437 }
1438
1439
map_word()1440 MapWord HeapObject::map_word() const {
1441 return MapWord(
1442 reinterpret_cast<uintptr_t>(NOBARRIER_READ_FIELD(this, kMapOffset)));
1443 }
1444
1445
set_map_word(MapWord map_word)1446 void HeapObject::set_map_word(MapWord map_word) {
1447 NOBARRIER_WRITE_FIELD(
1448 this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1449 }
1450
1451
synchronized_map_word()1452 MapWord HeapObject::synchronized_map_word() const {
1453 return MapWord(
1454 reinterpret_cast<uintptr_t>(ACQUIRE_READ_FIELD(this, kMapOffset)));
1455 }
1456
1457
synchronized_set_map_word(MapWord map_word)1458 void HeapObject::synchronized_set_map_word(MapWord map_word) {
1459 RELEASE_WRITE_FIELD(
1460 this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1461 }
1462
1463
FromAddress(Address address)1464 HeapObject* HeapObject::FromAddress(Address address) {
1465 DCHECK_TAG_ALIGNED(address);
1466 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1467 }
1468
1469
address()1470 Address HeapObject::address() {
1471 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1472 }
1473
1474
Size()1475 int HeapObject::Size() {
1476 return SizeFromMap(map());
1477 }
1478
1479
MayContainRawValues()1480 bool HeapObject::MayContainRawValues() {
1481 InstanceType type = map()->instance_type();
1482 if (type <= LAST_NAME_TYPE) {
1483 if (type == SYMBOL_TYPE) {
1484 return false;
1485 }
1486 DCHECK(type < FIRST_NONSTRING_TYPE);
1487 // There are four string representations: sequential strings, external
1488 // strings, cons strings, and sliced strings.
1489 // Only the former two contain raw values and no heap pointers (besides the
1490 // map-word).
1491 return ((type & kIsIndirectStringMask) != kIsIndirectStringTag);
1492 }
1493 // The ConstantPoolArray contains heap pointers, but also raw values.
1494 if (type == CONSTANT_POOL_ARRAY_TYPE) return true;
1495 return (type <= LAST_DATA_TYPE);
1496 }
1497
1498
IteratePointers(ObjectVisitor * v,int start,int end)1499 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1500 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1501 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1502 }
1503
1504
IteratePointer(ObjectVisitor * v,int offset)1505 void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1506 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1507 }
1508
1509
IterateNextCodeLink(ObjectVisitor * v,int offset)1510 void HeapObject::IterateNextCodeLink(ObjectVisitor* v, int offset) {
1511 v->VisitNextCodeLink(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1512 }
1513
1514
value()1515 double HeapNumber::value() const {
1516 return READ_DOUBLE_FIELD(this, kValueOffset);
1517 }
1518
1519
set_value(double value)1520 void HeapNumber::set_value(double value) {
1521 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1522 }
1523
1524
get_exponent()1525 int HeapNumber::get_exponent() {
1526 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1527 kExponentShift) - kExponentBias;
1528 }
1529
1530
get_sign()1531 int HeapNumber::get_sign() {
1532 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1533 }
1534
1535
ACCESSORS(JSObject,properties,FixedArray,kPropertiesOffset)1536 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1537
1538
1539 Object** FixedArray::GetFirstElementAddress() {
1540 return reinterpret_cast<Object**>(FIELD_ADDR(this, OffsetOfElementAt(0)));
1541 }
1542
1543
ContainsOnlySmisOrHoles()1544 bool FixedArray::ContainsOnlySmisOrHoles() {
1545 Object* the_hole = GetHeap()->the_hole_value();
1546 Object** current = GetFirstElementAddress();
1547 for (int i = 0; i < length(); ++i) {
1548 Object* candidate = *current++;
1549 if (!candidate->IsSmi() && candidate != the_hole) return false;
1550 }
1551 return true;
1552 }
1553
1554
elements()1555 FixedArrayBase* JSObject::elements() const {
1556 Object* array = READ_FIELD(this, kElementsOffset);
1557 return static_cast<FixedArrayBase*>(array);
1558 }
1559
1560
ValidateElements(Handle<JSObject> object)1561 void JSObject::ValidateElements(Handle<JSObject> object) {
1562 #ifdef ENABLE_SLOW_DCHECKS
1563 if (FLAG_enable_slow_asserts) {
1564 ElementsAccessor* accessor = object->GetElementsAccessor();
1565 accessor->Validate(object);
1566 }
1567 #endif
1568 }
1569
1570
Initialize()1571 void AllocationSite::Initialize() {
1572 set_transition_info(Smi::FromInt(0));
1573 SetElementsKind(GetInitialFastElementsKind());
1574 set_nested_site(Smi::FromInt(0));
1575 set_pretenure_data(Smi::FromInt(0));
1576 set_pretenure_create_count(Smi::FromInt(0));
1577 set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
1578 SKIP_WRITE_BARRIER);
1579 }
1580
1581
MarkZombie()1582 void AllocationSite::MarkZombie() {
1583 DCHECK(!IsZombie());
1584 Initialize();
1585 set_pretenure_decision(kZombie);
1586 }
1587
1588
1589 // Heuristic: We only need to create allocation site info if the boilerplate
1590 // elements kind is the initial elements kind.
GetMode(ElementsKind boilerplate_elements_kind)1591 AllocationSiteMode AllocationSite::GetMode(
1592 ElementsKind boilerplate_elements_kind) {
1593 if (FLAG_pretenuring_call_new ||
1594 IsFastSmiElementsKind(boilerplate_elements_kind)) {
1595 return TRACK_ALLOCATION_SITE;
1596 }
1597
1598 return DONT_TRACK_ALLOCATION_SITE;
1599 }
1600
1601
GetMode(ElementsKind from,ElementsKind to)1602 AllocationSiteMode AllocationSite::GetMode(ElementsKind from,
1603 ElementsKind to) {
1604 if (FLAG_pretenuring_call_new ||
1605 (IsFastSmiElementsKind(from) &&
1606 IsMoreGeneralElementsKindTransition(from, to))) {
1607 return TRACK_ALLOCATION_SITE;
1608 }
1609
1610 return DONT_TRACK_ALLOCATION_SITE;
1611 }
1612
1613
CanTrack(InstanceType type)1614 inline bool AllocationSite::CanTrack(InstanceType type) {
1615 if (FLAG_allocation_site_pretenuring) {
1616 return type == JS_ARRAY_TYPE ||
1617 type == JS_OBJECT_TYPE ||
1618 type < FIRST_NONSTRING_TYPE;
1619 }
1620 return type == JS_ARRAY_TYPE;
1621 }
1622
1623
ToDependencyGroup(Reason reason)1624 inline DependentCode::DependencyGroup AllocationSite::ToDependencyGroup(
1625 Reason reason) {
1626 switch (reason) {
1627 case TENURING:
1628 return DependentCode::kAllocationSiteTenuringChangedGroup;
1629 break;
1630 case TRANSITIONS:
1631 return DependentCode::kAllocationSiteTransitionChangedGroup;
1632 break;
1633 }
1634 UNREACHABLE();
1635 return DependentCode::kAllocationSiteTransitionChangedGroup;
1636 }
1637
1638
set_memento_found_count(int count)1639 inline void AllocationSite::set_memento_found_count(int count) {
1640 int value = pretenure_data()->value();
1641 // Verify that we can count more mementos than we can possibly find in one
1642 // new space collection.
1643 DCHECK((GetHeap()->MaxSemiSpaceSize() /
1644 (StaticVisitorBase::kMinObjectSizeInWords * kPointerSize +
1645 AllocationMemento::kSize)) < MementoFoundCountBits::kMax);
1646 DCHECK(count < MementoFoundCountBits::kMax);
1647 set_pretenure_data(
1648 Smi::FromInt(MementoFoundCountBits::update(value, count)),
1649 SKIP_WRITE_BARRIER);
1650 }
1651
IncrementMementoFoundCount()1652 inline bool AllocationSite::IncrementMementoFoundCount() {
1653 if (IsZombie()) return false;
1654
1655 int value = memento_found_count();
1656 set_memento_found_count(value + 1);
1657 return memento_found_count() == kPretenureMinimumCreated;
1658 }
1659
1660
IncrementMementoCreateCount()1661 inline void AllocationSite::IncrementMementoCreateCount() {
1662 DCHECK(FLAG_allocation_site_pretenuring);
1663 int value = memento_create_count();
1664 set_memento_create_count(value + 1);
1665 }
1666
1667
MakePretenureDecision(PretenureDecision current_decision,double ratio,bool maximum_size_scavenge)1668 inline bool AllocationSite::MakePretenureDecision(
1669 PretenureDecision current_decision,
1670 double ratio,
1671 bool maximum_size_scavenge) {
1672 // Here we just allow state transitions from undecided or maybe tenure
1673 // to don't tenure, maybe tenure, or tenure.
1674 if ((current_decision == kUndecided || current_decision == kMaybeTenure)) {
1675 if (ratio >= kPretenureRatio) {
1676 // We just transition into tenure state when the semi-space was at
1677 // maximum capacity.
1678 if (maximum_size_scavenge) {
1679 set_deopt_dependent_code(true);
1680 set_pretenure_decision(kTenure);
1681 // Currently we just need to deopt when we make a state transition to
1682 // tenure.
1683 return true;
1684 }
1685 set_pretenure_decision(kMaybeTenure);
1686 } else {
1687 set_pretenure_decision(kDontTenure);
1688 }
1689 }
1690 return false;
1691 }
1692
1693
DigestPretenuringFeedback(bool maximum_size_scavenge)1694 inline bool AllocationSite::DigestPretenuringFeedback(
1695 bool maximum_size_scavenge) {
1696 bool deopt = false;
1697 int create_count = memento_create_count();
1698 int found_count = memento_found_count();
1699 bool minimum_mementos_created = create_count >= kPretenureMinimumCreated;
1700 double ratio =
1701 minimum_mementos_created || FLAG_trace_pretenuring_statistics ?
1702 static_cast<double>(found_count) / create_count : 0.0;
1703 PretenureDecision current_decision = pretenure_decision();
1704
1705 if (minimum_mementos_created) {
1706 deopt = MakePretenureDecision(
1707 current_decision, ratio, maximum_size_scavenge);
1708 }
1709
1710 if (FLAG_trace_pretenuring_statistics) {
1711 PrintF(
1712 "AllocationSite(%p): (created, found, ratio) (%d, %d, %f) %s => %s\n",
1713 static_cast<void*>(this), create_count, found_count, ratio,
1714 PretenureDecisionName(current_decision),
1715 PretenureDecisionName(pretenure_decision()));
1716 }
1717
1718 // Clear feedback calculation fields until the next gc.
1719 set_memento_found_count(0);
1720 set_memento_create_count(0);
1721 return deopt;
1722 }
1723
1724
EnsureCanContainHeapObjectElements(Handle<JSObject> object)1725 void JSObject::EnsureCanContainHeapObjectElements(Handle<JSObject> object) {
1726 JSObject::ValidateElements(object);
1727 ElementsKind elements_kind = object->map()->elements_kind();
1728 if (!IsFastObjectElementsKind(elements_kind)) {
1729 if (IsFastHoleyElementsKind(elements_kind)) {
1730 TransitionElementsKind(object, FAST_HOLEY_ELEMENTS);
1731 } else {
1732 TransitionElementsKind(object, FAST_ELEMENTS);
1733 }
1734 }
1735 }
1736
1737
EnsureCanContainElements(Handle<JSObject> object,Object ** objects,uint32_t count,EnsureElementsMode mode)1738 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
1739 Object** objects,
1740 uint32_t count,
1741 EnsureElementsMode mode) {
1742 ElementsKind current_kind = object->map()->elements_kind();
1743 ElementsKind target_kind = current_kind;
1744 {
1745 DisallowHeapAllocation no_allocation;
1746 DCHECK(mode != ALLOW_COPIED_DOUBLE_ELEMENTS);
1747 bool is_holey = IsFastHoleyElementsKind(current_kind);
1748 if (current_kind == FAST_HOLEY_ELEMENTS) return;
1749 Heap* heap = object->GetHeap();
1750 Object* the_hole = heap->the_hole_value();
1751 for (uint32_t i = 0; i < count; ++i) {
1752 Object* current = *objects++;
1753 if (current == the_hole) {
1754 is_holey = true;
1755 target_kind = GetHoleyElementsKind(target_kind);
1756 } else if (!current->IsSmi()) {
1757 if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS && current->IsNumber()) {
1758 if (IsFastSmiElementsKind(target_kind)) {
1759 if (is_holey) {
1760 target_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
1761 } else {
1762 target_kind = FAST_DOUBLE_ELEMENTS;
1763 }
1764 }
1765 } else if (is_holey) {
1766 target_kind = FAST_HOLEY_ELEMENTS;
1767 break;
1768 } else {
1769 target_kind = FAST_ELEMENTS;
1770 }
1771 }
1772 }
1773 }
1774 if (target_kind != current_kind) {
1775 TransitionElementsKind(object, target_kind);
1776 }
1777 }
1778
1779
EnsureCanContainElements(Handle<JSObject> object,Handle<FixedArrayBase> elements,uint32_t length,EnsureElementsMode mode)1780 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
1781 Handle<FixedArrayBase> elements,
1782 uint32_t length,
1783 EnsureElementsMode mode) {
1784 Heap* heap = object->GetHeap();
1785 if (elements->map() != heap->fixed_double_array_map()) {
1786 DCHECK(elements->map() == heap->fixed_array_map() ||
1787 elements->map() == heap->fixed_cow_array_map());
1788 if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) {
1789 mode = DONT_ALLOW_DOUBLE_ELEMENTS;
1790 }
1791 Object** objects =
1792 Handle<FixedArray>::cast(elements)->GetFirstElementAddress();
1793 EnsureCanContainElements(object, objects, length, mode);
1794 return;
1795 }
1796
1797 DCHECK(mode == ALLOW_COPIED_DOUBLE_ELEMENTS);
1798 if (object->GetElementsKind() == FAST_HOLEY_SMI_ELEMENTS) {
1799 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS);
1800 } else if (object->GetElementsKind() == FAST_SMI_ELEMENTS) {
1801 Handle<FixedDoubleArray> double_array =
1802 Handle<FixedDoubleArray>::cast(elements);
1803 for (uint32_t i = 0; i < length; ++i) {
1804 if (double_array->is_the_hole(i)) {
1805 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS);
1806 return;
1807 }
1808 }
1809 TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS);
1810 }
1811 }
1812
1813
SetMapAndElements(Handle<JSObject> object,Handle<Map> new_map,Handle<FixedArrayBase> value)1814 void JSObject::SetMapAndElements(Handle<JSObject> object,
1815 Handle<Map> new_map,
1816 Handle<FixedArrayBase> value) {
1817 JSObject::MigrateToMap(object, new_map);
1818 DCHECK((object->map()->has_fast_smi_or_object_elements() ||
1819 (*value == object->GetHeap()->empty_fixed_array())) ==
1820 (value->map() == object->GetHeap()->fixed_array_map() ||
1821 value->map() == object->GetHeap()->fixed_cow_array_map()));
1822 DCHECK((*value == object->GetHeap()->empty_fixed_array()) ||
1823 (object->map()->has_fast_double_elements() ==
1824 value->IsFixedDoubleArray()));
1825 object->set_elements(*value);
1826 }
1827
1828
set_elements(FixedArrayBase * value,WriteBarrierMode mode)1829 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) {
1830 WRITE_FIELD(this, kElementsOffset, value);
1831 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode);
1832 }
1833
1834
initialize_properties()1835 void JSObject::initialize_properties() {
1836 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1837 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
1838 }
1839
1840
initialize_elements()1841 void JSObject::initialize_elements() {
1842 FixedArrayBase* elements = map()->GetInitialElements();
1843 WRITE_FIELD(this, kElementsOffset, elements);
1844 }
1845
1846
ExpectedTransitionKey(Handle<Map> map)1847 Handle<String> Map::ExpectedTransitionKey(Handle<Map> map) {
1848 DisallowHeapAllocation no_gc;
1849 if (!map->HasTransitionArray()) return Handle<String>::null();
1850 TransitionArray* transitions = map->transitions();
1851 if (!transitions->IsSimpleTransition()) return Handle<String>::null();
1852 int transition = TransitionArray::kSimpleTransitionIndex;
1853 PropertyDetails details = transitions->GetTargetDetails(transition);
1854 Name* name = transitions->GetKey(transition);
1855 if (details.type() != FIELD) return Handle<String>::null();
1856 if (details.attributes() != NONE) return Handle<String>::null();
1857 if (!name->IsString()) return Handle<String>::null();
1858 return Handle<String>(String::cast(name));
1859 }
1860
1861
ExpectedTransitionTarget(Handle<Map> map)1862 Handle<Map> Map::ExpectedTransitionTarget(Handle<Map> map) {
1863 DCHECK(!ExpectedTransitionKey(map).is_null());
1864 return Handle<Map>(map->transitions()->GetTarget(
1865 TransitionArray::kSimpleTransitionIndex));
1866 }
1867
1868
FindTransitionToField(Handle<Map> map,Handle<Name> key)1869 Handle<Map> Map::FindTransitionToField(Handle<Map> map, Handle<Name> key) {
1870 DisallowHeapAllocation no_allocation;
1871 if (!map->HasTransitionArray()) return Handle<Map>::null();
1872 TransitionArray* transitions = map->transitions();
1873 int transition = transitions->Search(*key);
1874 if (transition == TransitionArray::kNotFound) return Handle<Map>::null();
1875 PropertyDetails target_details = transitions->GetTargetDetails(transition);
1876 if (target_details.type() != FIELD) return Handle<Map>::null();
1877 if (target_details.attributes() != NONE) return Handle<Map>::null();
1878 return Handle<Map>(transitions->GetTarget(transition));
1879 }
1880
1881
ACCESSORS(Oddball,to_string,String,kToStringOffset)1882 ACCESSORS(Oddball, to_string, String, kToStringOffset)
1883 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1884
1885
1886 byte Oddball::kind() const {
1887 return Smi::cast(READ_FIELD(this, kKindOffset))->value();
1888 }
1889
1890
set_kind(byte value)1891 void Oddball::set_kind(byte value) {
1892 WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
1893 }
1894
1895
value()1896 Object* Cell::value() const {
1897 return READ_FIELD(this, kValueOffset);
1898 }
1899
1900
set_value(Object * val,WriteBarrierMode ignored)1901 void Cell::set_value(Object* val, WriteBarrierMode ignored) {
1902 // The write barrier is not used for global property cells.
1903 DCHECK(!val->IsPropertyCell() && !val->IsCell());
1904 WRITE_FIELD(this, kValueOffset, val);
1905 }
1906
ACCESSORS(PropertyCell,dependent_code,DependentCode,kDependentCodeOffset)1907 ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset)
1908
1909 Object* PropertyCell::type_raw() const {
1910 return READ_FIELD(this, kTypeOffset);
1911 }
1912
1913
set_type_raw(Object * val,WriteBarrierMode ignored)1914 void PropertyCell::set_type_raw(Object* val, WriteBarrierMode ignored) {
1915 WRITE_FIELD(this, kTypeOffset, val);
1916 }
1917
1918
GetHeaderSize()1919 int JSObject::GetHeaderSize() {
1920 InstanceType type = map()->instance_type();
1921 // Check for the most common kind of JavaScript object before
1922 // falling into the generic switch. This speeds up the internal
1923 // field operations considerably on average.
1924 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1925 switch (type) {
1926 case JS_GENERATOR_OBJECT_TYPE:
1927 return JSGeneratorObject::kSize;
1928 case JS_MODULE_TYPE:
1929 return JSModule::kSize;
1930 case JS_GLOBAL_PROXY_TYPE:
1931 return JSGlobalProxy::kSize;
1932 case JS_GLOBAL_OBJECT_TYPE:
1933 return JSGlobalObject::kSize;
1934 case JS_BUILTINS_OBJECT_TYPE:
1935 return JSBuiltinsObject::kSize;
1936 case JS_FUNCTION_TYPE:
1937 return JSFunction::kSize;
1938 case JS_VALUE_TYPE:
1939 return JSValue::kSize;
1940 case JS_DATE_TYPE:
1941 return JSDate::kSize;
1942 case JS_ARRAY_TYPE:
1943 return JSArray::kSize;
1944 case JS_ARRAY_BUFFER_TYPE:
1945 return JSArrayBuffer::kSize;
1946 case JS_TYPED_ARRAY_TYPE:
1947 return JSTypedArray::kSize;
1948 case JS_DATA_VIEW_TYPE:
1949 return JSDataView::kSize;
1950 case JS_SET_TYPE:
1951 return JSSet::kSize;
1952 case JS_MAP_TYPE:
1953 return JSMap::kSize;
1954 case JS_SET_ITERATOR_TYPE:
1955 return JSSetIterator::kSize;
1956 case JS_MAP_ITERATOR_TYPE:
1957 return JSMapIterator::kSize;
1958 case JS_WEAK_MAP_TYPE:
1959 return JSWeakMap::kSize;
1960 case JS_WEAK_SET_TYPE:
1961 return JSWeakSet::kSize;
1962 case JS_REGEXP_TYPE:
1963 return JSRegExp::kSize;
1964 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1965 return JSObject::kHeaderSize;
1966 case JS_MESSAGE_OBJECT_TYPE:
1967 return JSMessageObject::kSize;
1968 default:
1969 // TODO(jkummerow): Re-enable this. Blink currently hits this
1970 // from its CustomElementConstructorBuilder.
1971 // UNREACHABLE();
1972 return 0;
1973 }
1974 }
1975
1976
GetInternalFieldCount()1977 int JSObject::GetInternalFieldCount() {
1978 DCHECK(1 << kPointerSizeLog2 == kPointerSize);
1979 // Make sure to adjust for the number of in-object properties. These
1980 // properties do contribute to the size, but are not internal fields.
1981 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1982 map()->inobject_properties();
1983 }
1984
1985
GetInternalFieldOffset(int index)1986 int JSObject::GetInternalFieldOffset(int index) {
1987 DCHECK(index < GetInternalFieldCount() && index >= 0);
1988 return GetHeaderSize() + (kPointerSize * index);
1989 }
1990
1991
GetInternalField(int index)1992 Object* JSObject::GetInternalField(int index) {
1993 DCHECK(index < GetInternalFieldCount() && index >= 0);
1994 // Internal objects do follow immediately after the header, whereas in-object
1995 // properties are at the end of the object. Therefore there is no need
1996 // to adjust the index here.
1997 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1998 }
1999
2000
SetInternalField(int index,Object * value)2001 void JSObject::SetInternalField(int index, Object* value) {
2002 DCHECK(index < GetInternalFieldCount() && index >= 0);
2003 // Internal objects do follow immediately after the header, whereas in-object
2004 // properties are at the end of the object. Therefore there is no need
2005 // to adjust the index here.
2006 int offset = GetHeaderSize() + (kPointerSize * index);
2007 WRITE_FIELD(this, offset, value);
2008 WRITE_BARRIER(GetHeap(), this, offset, value);
2009 }
2010
2011
SetInternalField(int index,Smi * value)2012 void JSObject::SetInternalField(int index, Smi* value) {
2013 DCHECK(index < GetInternalFieldCount() && index >= 0);
2014 // Internal objects do follow immediately after the header, whereas in-object
2015 // properties are at the end of the object. Therefore there is no need
2016 // to adjust the index here.
2017 int offset = GetHeaderSize() + (kPointerSize * index);
2018 WRITE_FIELD(this, offset, value);
2019 }
2020
2021
2022 // Access fast-case object properties at index. The use of these routines
2023 // is needed to correctly distinguish between properties stored in-object and
2024 // properties stored in the properties array.
RawFastPropertyAt(FieldIndex index)2025 Object* JSObject::RawFastPropertyAt(FieldIndex index) {
2026 if (index.is_inobject()) {
2027 return READ_FIELD(this, index.offset());
2028 } else {
2029 return properties()->get(index.outobject_array_index());
2030 }
2031 }
2032
2033
FastPropertyAtPut(FieldIndex index,Object * value)2034 void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) {
2035 if (index.is_inobject()) {
2036 int offset = index.offset();
2037 WRITE_FIELD(this, offset, value);
2038 WRITE_BARRIER(GetHeap(), this, offset, value);
2039 } else {
2040 properties()->set(index.outobject_array_index(), value);
2041 }
2042 }
2043
2044
GetInObjectPropertyOffset(int index)2045 int JSObject::GetInObjectPropertyOffset(int index) {
2046 return map()->GetInObjectPropertyOffset(index);
2047 }
2048
2049
InObjectPropertyAt(int index)2050 Object* JSObject::InObjectPropertyAt(int index) {
2051 int offset = GetInObjectPropertyOffset(index);
2052 return READ_FIELD(this, offset);
2053 }
2054
2055
InObjectPropertyAtPut(int index,Object * value,WriteBarrierMode mode)2056 Object* JSObject::InObjectPropertyAtPut(int index,
2057 Object* value,
2058 WriteBarrierMode mode) {
2059 // Adjust for the number of properties stored in the object.
2060 int offset = GetInObjectPropertyOffset(index);
2061 WRITE_FIELD(this, offset, value);
2062 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
2063 return value;
2064 }
2065
2066
2067
InitializeBody(Map * map,Object * pre_allocated_value,Object * filler_value)2068 void JSObject::InitializeBody(Map* map,
2069 Object* pre_allocated_value,
2070 Object* filler_value) {
2071 DCHECK(!filler_value->IsHeapObject() ||
2072 !GetHeap()->InNewSpace(filler_value));
2073 DCHECK(!pre_allocated_value->IsHeapObject() ||
2074 !GetHeap()->InNewSpace(pre_allocated_value));
2075 int size = map->instance_size();
2076 int offset = kHeaderSize;
2077 if (filler_value != pre_allocated_value) {
2078 int pre_allocated = map->pre_allocated_property_fields();
2079 DCHECK(pre_allocated * kPointerSize + kHeaderSize <= size);
2080 for (int i = 0; i < pre_allocated; i++) {
2081 WRITE_FIELD(this, offset, pre_allocated_value);
2082 offset += kPointerSize;
2083 }
2084 }
2085 while (offset < size) {
2086 WRITE_FIELD(this, offset, filler_value);
2087 offset += kPointerSize;
2088 }
2089 }
2090
2091
HasFastProperties()2092 bool JSObject::HasFastProperties() {
2093 DCHECK(properties()->IsDictionary() == map()->is_dictionary_map());
2094 return !properties()->IsDictionary();
2095 }
2096
2097
TooManyFastProperties(StoreFromKeyed store_mode)2098 bool Map::TooManyFastProperties(StoreFromKeyed store_mode) {
2099 if (unused_property_fields() != 0) return false;
2100 if (is_prototype_map()) return false;
2101 int minimum = store_mode == CERTAINLY_NOT_STORE_FROM_KEYED ? 128 : 12;
2102 int limit = Max(minimum, inobject_properties());
2103 int external = NumberOfFields() - inobject_properties();
2104 return external > limit;
2105 }
2106
2107
InitializeBody(int object_size)2108 void Struct::InitializeBody(int object_size) {
2109 Object* value = GetHeap()->undefined_value();
2110 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
2111 WRITE_FIELD(this, offset, value);
2112 }
2113 }
2114
2115
ToArrayIndex(uint32_t * index)2116 bool Object::ToArrayIndex(uint32_t* index) {
2117 if (IsSmi()) {
2118 int value = Smi::cast(this)->value();
2119 if (value < 0) return false;
2120 *index = value;
2121 return true;
2122 }
2123 if (IsHeapNumber()) {
2124 double value = HeapNumber::cast(this)->value();
2125 uint32_t uint_value = static_cast<uint32_t>(value);
2126 if (value == static_cast<double>(uint_value)) {
2127 *index = uint_value;
2128 return true;
2129 }
2130 }
2131 return false;
2132 }
2133
2134
IsStringObjectWithCharacterAt(uint32_t index)2135 bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
2136 if (!this->IsJSValue()) return false;
2137
2138 JSValue* js_value = JSValue::cast(this);
2139 if (!js_value->value()->IsString()) return false;
2140
2141 String* str = String::cast(js_value->value());
2142 if (index >= static_cast<uint32_t>(str->length())) return false;
2143
2144 return true;
2145 }
2146
2147
VerifyApiCallResultType()2148 void Object::VerifyApiCallResultType() {
2149 #if ENABLE_EXTRA_CHECKS
2150 if (!(IsSmi() ||
2151 IsString() ||
2152 IsSymbol() ||
2153 IsSpecObject() ||
2154 IsHeapNumber() ||
2155 IsUndefined() ||
2156 IsTrue() ||
2157 IsFalse() ||
2158 IsNull())) {
2159 FATAL("API call returned invalid object");
2160 }
2161 #endif // ENABLE_EXTRA_CHECKS
2162 }
2163
2164
get(int index)2165 Object* FixedArray::get(int index) {
2166 SLOW_DCHECK(index >= 0 && index < this->length());
2167 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
2168 }
2169
2170
get(Handle<FixedArray> array,int index)2171 Handle<Object> FixedArray::get(Handle<FixedArray> array, int index) {
2172 return handle(array->get(index), array->GetIsolate());
2173 }
2174
2175
is_the_hole(int index)2176 bool FixedArray::is_the_hole(int index) {
2177 return get(index) == GetHeap()->the_hole_value();
2178 }
2179
2180
set(int index,Smi * value)2181 void FixedArray::set(int index, Smi* value) {
2182 DCHECK(map() != GetHeap()->fixed_cow_array_map());
2183 DCHECK(index >= 0 && index < this->length());
2184 DCHECK(reinterpret_cast<Object*>(value)->IsSmi());
2185 int offset = kHeaderSize + index * kPointerSize;
2186 WRITE_FIELD(this, offset, value);
2187 }
2188
2189
set(int index,Object * value)2190 void FixedArray::set(int index, Object* value) {
2191 DCHECK_NE(GetHeap()->fixed_cow_array_map(), map());
2192 DCHECK_EQ(FIXED_ARRAY_TYPE, map()->instance_type());
2193 DCHECK(index >= 0 && index < this->length());
2194 int offset = kHeaderSize + index * kPointerSize;
2195 WRITE_FIELD(this, offset, value);
2196 WRITE_BARRIER(GetHeap(), this, offset, value);
2197 }
2198
2199
is_the_hole_nan(double value)2200 inline bool FixedDoubleArray::is_the_hole_nan(double value) {
2201 return bit_cast<uint64_t, double>(value) == kHoleNanInt64;
2202 }
2203
2204
hole_nan_as_double()2205 inline double FixedDoubleArray::hole_nan_as_double() {
2206 return bit_cast<double, uint64_t>(kHoleNanInt64);
2207 }
2208
2209
canonical_not_the_hole_nan_as_double()2210 inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
2211 DCHECK(bit_cast<uint64_t>(base::OS::nan_value()) != kHoleNanInt64);
2212 DCHECK((bit_cast<uint64_t>(base::OS::nan_value()) >> 32) != kHoleNanUpper32);
2213 return base::OS::nan_value();
2214 }
2215
2216
get_scalar(int index)2217 double FixedDoubleArray::get_scalar(int index) {
2218 DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
2219 map() != GetHeap()->fixed_array_map());
2220 DCHECK(index >= 0 && index < this->length());
2221 double result = READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
2222 DCHECK(!is_the_hole_nan(result));
2223 return result;
2224 }
2225
get_representation(int index)2226 int64_t FixedDoubleArray::get_representation(int index) {
2227 DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
2228 map() != GetHeap()->fixed_array_map());
2229 DCHECK(index >= 0 && index < this->length());
2230 return READ_INT64_FIELD(this, kHeaderSize + index * kDoubleSize);
2231 }
2232
2233
get(Handle<FixedDoubleArray> array,int index)2234 Handle<Object> FixedDoubleArray::get(Handle<FixedDoubleArray> array,
2235 int index) {
2236 if (array->is_the_hole(index)) {
2237 return array->GetIsolate()->factory()->the_hole_value();
2238 } else {
2239 return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index));
2240 }
2241 }
2242
2243
set(int index,double value)2244 void FixedDoubleArray::set(int index, double value) {
2245 DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
2246 map() != GetHeap()->fixed_array_map());
2247 int offset = kHeaderSize + index * kDoubleSize;
2248 if (std::isnan(value)) value = canonical_not_the_hole_nan_as_double();
2249 WRITE_DOUBLE_FIELD(this, offset, value);
2250 }
2251
2252
set_the_hole(int index)2253 void FixedDoubleArray::set_the_hole(int index) {
2254 DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
2255 map() != GetHeap()->fixed_array_map());
2256 int offset = kHeaderSize + index * kDoubleSize;
2257 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
2258 }
2259
2260
is_the_hole(int index)2261 bool FixedDoubleArray::is_the_hole(int index) {
2262 int offset = kHeaderSize + index * kDoubleSize;
2263 return is_the_hole_nan(READ_DOUBLE_FIELD(this, offset));
2264 }
2265
2266
data_start()2267 double* FixedDoubleArray::data_start() {
2268 return reinterpret_cast<double*>(FIELD_ADDR(this, kHeaderSize));
2269 }
2270
2271
FillWithHoles(int from,int to)2272 void FixedDoubleArray::FillWithHoles(int from, int to) {
2273 for (int i = from; i < to; i++) {
2274 set_the_hole(i);
2275 }
2276 }
2277
2278
increment(Type type)2279 void ConstantPoolArray::NumberOfEntries::increment(Type type) {
2280 DCHECK(type < NUMBER_OF_TYPES);
2281 element_counts_[type]++;
2282 }
2283
2284
equals(const ConstantPoolArray::NumberOfEntries & other)2285 int ConstantPoolArray::NumberOfEntries::equals(
2286 const ConstantPoolArray::NumberOfEntries& other) const {
2287 for (int i = 0; i < NUMBER_OF_TYPES; i++) {
2288 if (element_counts_[i] != other.element_counts_[i]) return false;
2289 }
2290 return true;
2291 }
2292
2293
is_empty()2294 bool ConstantPoolArray::NumberOfEntries::is_empty() const {
2295 return total_count() == 0;
2296 }
2297
2298
count_of(Type type)2299 int ConstantPoolArray::NumberOfEntries::count_of(Type type) const {
2300 DCHECK(type < NUMBER_OF_TYPES);
2301 return element_counts_[type];
2302 }
2303
2304
base_of(Type type)2305 int ConstantPoolArray::NumberOfEntries::base_of(Type type) const {
2306 int base = 0;
2307 DCHECK(type < NUMBER_OF_TYPES);
2308 for (int i = 0; i < type; i++) {
2309 base += element_counts_[i];
2310 }
2311 return base;
2312 }
2313
2314
total_count()2315 int ConstantPoolArray::NumberOfEntries::total_count() const {
2316 int count = 0;
2317 for (int i = 0; i < NUMBER_OF_TYPES; i++) {
2318 count += element_counts_[i];
2319 }
2320 return count;
2321 }
2322
2323
are_in_range(int min,int max)2324 int ConstantPoolArray::NumberOfEntries::are_in_range(int min, int max) const {
2325 for (int i = FIRST_TYPE; i < NUMBER_OF_TYPES; i++) {
2326 if (element_counts_[i] < min || element_counts_[i] > max) {
2327 return false;
2328 }
2329 }
2330 return true;
2331 }
2332
2333
next_index()2334 int ConstantPoolArray::Iterator::next_index() {
2335 DCHECK(!is_finished());
2336 int ret = next_index_++;
2337 update_section();
2338 return ret;
2339 }
2340
2341
is_finished()2342 bool ConstantPoolArray::Iterator::is_finished() {
2343 return next_index_ > array_->last_index(type_, final_section_);
2344 }
2345
2346
update_section()2347 void ConstantPoolArray::Iterator::update_section() {
2348 if (next_index_ > array_->last_index(type_, current_section_) &&
2349 current_section_ != final_section_) {
2350 DCHECK(final_section_ == EXTENDED_SECTION);
2351 current_section_ = EXTENDED_SECTION;
2352 next_index_ = array_->first_index(type_, EXTENDED_SECTION);
2353 }
2354 }
2355
2356
is_extended_layout()2357 bool ConstantPoolArray::is_extended_layout() {
2358 uint32_t small_layout_1 = READ_UINT32_FIELD(this, kSmallLayout1Offset);
2359 return IsExtendedField::decode(small_layout_1);
2360 }
2361
2362
final_section()2363 ConstantPoolArray::LayoutSection ConstantPoolArray::final_section() {
2364 return is_extended_layout() ? EXTENDED_SECTION : SMALL_SECTION;
2365 }
2366
2367
first_extended_section_index()2368 int ConstantPoolArray::first_extended_section_index() {
2369 DCHECK(is_extended_layout());
2370 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2371 return TotalCountField::decode(small_layout_2);
2372 }
2373
2374
get_extended_section_header_offset()2375 int ConstantPoolArray::get_extended_section_header_offset() {
2376 return RoundUp(SizeFor(NumberOfEntries(this, SMALL_SECTION)), kInt64Size);
2377 }
2378
2379
get_weak_object_state()2380 ConstantPoolArray::WeakObjectState ConstantPoolArray::get_weak_object_state() {
2381 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2382 return WeakObjectStateField::decode(small_layout_2);
2383 }
2384
2385
set_weak_object_state(ConstantPoolArray::WeakObjectState state)2386 void ConstantPoolArray::set_weak_object_state(
2387 ConstantPoolArray::WeakObjectState state) {
2388 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2389 small_layout_2 = WeakObjectStateField::update(small_layout_2, state);
2390 WRITE_INT32_FIELD(this, kSmallLayout2Offset, small_layout_2);
2391 }
2392
2393
first_index(Type type,LayoutSection section)2394 int ConstantPoolArray::first_index(Type type, LayoutSection section) {
2395 int index = 0;
2396 if (section == EXTENDED_SECTION) {
2397 DCHECK(is_extended_layout());
2398 index += first_extended_section_index();
2399 }
2400
2401 for (Type type_iter = FIRST_TYPE; type_iter < type;
2402 type_iter = next_type(type_iter)) {
2403 index += number_of_entries(type_iter, section);
2404 }
2405
2406 return index;
2407 }
2408
2409
last_index(Type type,LayoutSection section)2410 int ConstantPoolArray::last_index(Type type, LayoutSection section) {
2411 return first_index(type, section) + number_of_entries(type, section) - 1;
2412 }
2413
2414
number_of_entries(Type type,LayoutSection section)2415 int ConstantPoolArray::number_of_entries(Type type, LayoutSection section) {
2416 if (section == SMALL_SECTION) {
2417 uint32_t small_layout_1 = READ_UINT32_FIELD(this, kSmallLayout1Offset);
2418 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2419 switch (type) {
2420 case INT64:
2421 return Int64CountField::decode(small_layout_1);
2422 case CODE_PTR:
2423 return CodePtrCountField::decode(small_layout_1);
2424 case HEAP_PTR:
2425 return HeapPtrCountField::decode(small_layout_1);
2426 case INT32:
2427 return Int32CountField::decode(small_layout_2);
2428 default:
2429 UNREACHABLE();
2430 return 0;
2431 }
2432 } else {
2433 DCHECK(section == EXTENDED_SECTION && is_extended_layout());
2434 int offset = get_extended_section_header_offset();
2435 switch (type) {
2436 case INT64:
2437 offset += kExtendedInt64CountOffset;
2438 break;
2439 case CODE_PTR:
2440 offset += kExtendedCodePtrCountOffset;
2441 break;
2442 case HEAP_PTR:
2443 offset += kExtendedHeapPtrCountOffset;
2444 break;
2445 case INT32:
2446 offset += kExtendedInt32CountOffset;
2447 break;
2448 default:
2449 UNREACHABLE();
2450 }
2451 return READ_INT_FIELD(this, offset);
2452 }
2453 }
2454
2455
offset_is_type(int offset,Type type)2456 bool ConstantPoolArray::offset_is_type(int offset, Type type) {
2457 return (offset >= OffsetOfElementAt(first_index(type, SMALL_SECTION)) &&
2458 offset <= OffsetOfElementAt(last_index(type, SMALL_SECTION))) ||
2459 (is_extended_layout() &&
2460 offset >= OffsetOfElementAt(first_index(type, EXTENDED_SECTION)) &&
2461 offset <= OffsetOfElementAt(last_index(type, EXTENDED_SECTION)));
2462 }
2463
2464
get_type(int index)2465 ConstantPoolArray::Type ConstantPoolArray::get_type(int index) {
2466 LayoutSection section;
2467 if (is_extended_layout() && index >= first_extended_section_index()) {
2468 section = EXTENDED_SECTION;
2469 } else {
2470 section = SMALL_SECTION;
2471 }
2472
2473 Type type = FIRST_TYPE;
2474 while (index > last_index(type, section)) {
2475 type = next_type(type);
2476 }
2477 DCHECK(type <= LAST_TYPE);
2478 return type;
2479 }
2480
2481
get_int64_entry(int index)2482 int64_t ConstantPoolArray::get_int64_entry(int index) {
2483 DCHECK(map() == GetHeap()->constant_pool_array_map());
2484 DCHECK(get_type(index) == INT64);
2485 return READ_INT64_FIELD(this, OffsetOfElementAt(index));
2486 }
2487
2488
get_int64_entry_as_double(int index)2489 double ConstantPoolArray::get_int64_entry_as_double(int index) {
2490 STATIC_ASSERT(kDoubleSize == kInt64Size);
2491 DCHECK(map() == GetHeap()->constant_pool_array_map());
2492 DCHECK(get_type(index) == INT64);
2493 return READ_DOUBLE_FIELD(this, OffsetOfElementAt(index));
2494 }
2495
2496
get_code_ptr_entry(int index)2497 Address ConstantPoolArray::get_code_ptr_entry(int index) {
2498 DCHECK(map() == GetHeap()->constant_pool_array_map());
2499 DCHECK(get_type(index) == CODE_PTR);
2500 return reinterpret_cast<Address>(READ_FIELD(this, OffsetOfElementAt(index)));
2501 }
2502
2503
get_heap_ptr_entry(int index)2504 Object* ConstantPoolArray::get_heap_ptr_entry(int index) {
2505 DCHECK(map() == GetHeap()->constant_pool_array_map());
2506 DCHECK(get_type(index) == HEAP_PTR);
2507 return READ_FIELD(this, OffsetOfElementAt(index));
2508 }
2509
2510
get_int32_entry(int index)2511 int32_t ConstantPoolArray::get_int32_entry(int index) {
2512 DCHECK(map() == GetHeap()->constant_pool_array_map());
2513 DCHECK(get_type(index) == INT32);
2514 return READ_INT32_FIELD(this, OffsetOfElementAt(index));
2515 }
2516
2517
set(int index,int64_t value)2518 void ConstantPoolArray::set(int index, int64_t value) {
2519 DCHECK(map() == GetHeap()->constant_pool_array_map());
2520 DCHECK(get_type(index) == INT64);
2521 WRITE_INT64_FIELD(this, OffsetOfElementAt(index), value);
2522 }
2523
2524
set(int index,double value)2525 void ConstantPoolArray::set(int index, double value) {
2526 STATIC_ASSERT(kDoubleSize == kInt64Size);
2527 DCHECK(map() == GetHeap()->constant_pool_array_map());
2528 DCHECK(get_type(index) == INT64);
2529 WRITE_DOUBLE_FIELD(this, OffsetOfElementAt(index), value);
2530 }
2531
2532
set(int index,Address value)2533 void ConstantPoolArray::set(int index, Address value) {
2534 DCHECK(map() == GetHeap()->constant_pool_array_map());
2535 DCHECK(get_type(index) == CODE_PTR);
2536 WRITE_FIELD(this, OffsetOfElementAt(index), reinterpret_cast<Object*>(value));
2537 }
2538
2539
set(int index,Object * value)2540 void ConstantPoolArray::set(int index, Object* value) {
2541 DCHECK(map() == GetHeap()->constant_pool_array_map());
2542 DCHECK(!GetHeap()->InNewSpace(value));
2543 DCHECK(get_type(index) == HEAP_PTR);
2544 WRITE_FIELD(this, OffsetOfElementAt(index), value);
2545 WRITE_BARRIER(GetHeap(), this, OffsetOfElementAt(index), value);
2546 }
2547
2548
set(int index,int32_t value)2549 void ConstantPoolArray::set(int index, int32_t value) {
2550 DCHECK(map() == GetHeap()->constant_pool_array_map());
2551 DCHECK(get_type(index) == INT32);
2552 WRITE_INT32_FIELD(this, OffsetOfElementAt(index), value);
2553 }
2554
2555
set_at_offset(int offset,int32_t value)2556 void ConstantPoolArray::set_at_offset(int offset, int32_t value) {
2557 DCHECK(map() == GetHeap()->constant_pool_array_map());
2558 DCHECK(offset_is_type(offset, INT32));
2559 WRITE_INT32_FIELD(this, offset, value);
2560 }
2561
2562
set_at_offset(int offset,int64_t value)2563 void ConstantPoolArray::set_at_offset(int offset, int64_t value) {
2564 DCHECK(map() == GetHeap()->constant_pool_array_map());
2565 DCHECK(offset_is_type(offset, INT64));
2566 WRITE_INT64_FIELD(this, offset, value);
2567 }
2568
2569
set_at_offset(int offset,double value)2570 void ConstantPoolArray::set_at_offset(int offset, double value) {
2571 DCHECK(map() == GetHeap()->constant_pool_array_map());
2572 DCHECK(offset_is_type(offset, INT64));
2573 WRITE_DOUBLE_FIELD(this, offset, value);
2574 }
2575
2576
set_at_offset(int offset,Address value)2577 void ConstantPoolArray::set_at_offset(int offset, Address value) {
2578 DCHECK(map() == GetHeap()->constant_pool_array_map());
2579 DCHECK(offset_is_type(offset, CODE_PTR));
2580 WRITE_FIELD(this, offset, reinterpret_cast<Object*>(value));
2581 WRITE_BARRIER(GetHeap(), this, offset, reinterpret_cast<Object*>(value));
2582 }
2583
2584
set_at_offset(int offset,Object * value)2585 void ConstantPoolArray::set_at_offset(int offset, Object* value) {
2586 DCHECK(map() == GetHeap()->constant_pool_array_map());
2587 DCHECK(!GetHeap()->InNewSpace(value));
2588 DCHECK(offset_is_type(offset, HEAP_PTR));
2589 WRITE_FIELD(this, offset, value);
2590 WRITE_BARRIER(GetHeap(), this, offset, value);
2591 }
2592
2593
Init(const NumberOfEntries & small)2594 void ConstantPoolArray::Init(const NumberOfEntries& small) {
2595 uint32_t small_layout_1 =
2596 Int64CountField::encode(small.count_of(INT64)) |
2597 CodePtrCountField::encode(small.count_of(CODE_PTR)) |
2598 HeapPtrCountField::encode(small.count_of(HEAP_PTR)) |
2599 IsExtendedField::encode(false);
2600 uint32_t small_layout_2 =
2601 Int32CountField::encode(small.count_of(INT32)) |
2602 TotalCountField::encode(small.total_count()) |
2603 WeakObjectStateField::encode(NO_WEAK_OBJECTS);
2604 WRITE_UINT32_FIELD(this, kSmallLayout1Offset, small_layout_1);
2605 WRITE_UINT32_FIELD(this, kSmallLayout2Offset, small_layout_2);
2606 if (kHeaderSize != kFirstEntryOffset) {
2607 DCHECK(kFirstEntryOffset - kHeaderSize == kInt32Size);
2608 WRITE_UINT32_FIELD(this, kHeaderSize, 0); // Zero out header padding.
2609 }
2610 }
2611
2612
InitExtended(const NumberOfEntries & small,const NumberOfEntries & extended)2613 void ConstantPoolArray::InitExtended(const NumberOfEntries& small,
2614 const NumberOfEntries& extended) {
2615 // Initialize small layout fields first.
2616 Init(small);
2617
2618 // Set is_extended_layout field.
2619 uint32_t small_layout_1 = READ_UINT32_FIELD(this, kSmallLayout1Offset);
2620 small_layout_1 = IsExtendedField::update(small_layout_1, true);
2621 WRITE_INT32_FIELD(this, kSmallLayout1Offset, small_layout_1);
2622
2623 // Initialize the extended layout fields.
2624 int extended_header_offset = get_extended_section_header_offset();
2625 WRITE_INT_FIELD(this, extended_header_offset + kExtendedInt64CountOffset,
2626 extended.count_of(INT64));
2627 WRITE_INT_FIELD(this, extended_header_offset + kExtendedCodePtrCountOffset,
2628 extended.count_of(CODE_PTR));
2629 WRITE_INT_FIELD(this, extended_header_offset + kExtendedHeapPtrCountOffset,
2630 extended.count_of(HEAP_PTR));
2631 WRITE_INT_FIELD(this, extended_header_offset + kExtendedInt32CountOffset,
2632 extended.count_of(INT32));
2633 }
2634
2635
size()2636 int ConstantPoolArray::size() {
2637 NumberOfEntries small(this, SMALL_SECTION);
2638 if (!is_extended_layout()) {
2639 return SizeFor(small);
2640 } else {
2641 NumberOfEntries extended(this, EXTENDED_SECTION);
2642 return SizeForExtended(small, extended);
2643 }
2644 }
2645
2646
length()2647 int ConstantPoolArray::length() {
2648 uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset);
2649 int length = TotalCountField::decode(small_layout_2);
2650 if (is_extended_layout()) {
2651 length += number_of_entries(INT64, EXTENDED_SECTION) +
2652 number_of_entries(CODE_PTR, EXTENDED_SECTION) +
2653 number_of_entries(HEAP_PTR, EXTENDED_SECTION) +
2654 number_of_entries(INT32, EXTENDED_SECTION);
2655 }
2656 return length;
2657 }
2658
2659
GetWriteBarrierMode(const DisallowHeapAllocation & promise)2660 WriteBarrierMode HeapObject::GetWriteBarrierMode(
2661 const DisallowHeapAllocation& promise) {
2662 Heap* heap = GetHeap();
2663 if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
2664 if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER;
2665 return UPDATE_WRITE_BARRIER;
2666 }
2667
2668
set(int index,Object * value,WriteBarrierMode mode)2669 void FixedArray::set(int index,
2670 Object* value,
2671 WriteBarrierMode mode) {
2672 DCHECK(map() != GetHeap()->fixed_cow_array_map());
2673 DCHECK(index >= 0 && index < this->length());
2674 int offset = kHeaderSize + index * kPointerSize;
2675 WRITE_FIELD(this, offset, value);
2676 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
2677 }
2678
2679
NoIncrementalWriteBarrierSet(FixedArray * array,int index,Object * value)2680 void FixedArray::NoIncrementalWriteBarrierSet(FixedArray* array,
2681 int index,
2682 Object* value) {
2683 DCHECK(array->map() != array->GetHeap()->fixed_cow_array_map());
2684 DCHECK(index >= 0 && index < array->length());
2685 int offset = kHeaderSize + index * kPointerSize;
2686 WRITE_FIELD(array, offset, value);
2687 Heap* heap = array->GetHeap();
2688 if (heap->InNewSpace(value)) {
2689 heap->RecordWrite(array->address(), offset);
2690 }
2691 }
2692
2693
NoWriteBarrierSet(FixedArray * array,int index,Object * value)2694 void FixedArray::NoWriteBarrierSet(FixedArray* array,
2695 int index,
2696 Object* value) {
2697 DCHECK(array->map() != array->GetHeap()->fixed_cow_array_map());
2698 DCHECK(index >= 0 && index < array->length());
2699 DCHECK(!array->GetHeap()->InNewSpace(value));
2700 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
2701 }
2702
2703
set_undefined(int index)2704 void FixedArray::set_undefined(int index) {
2705 DCHECK(map() != GetHeap()->fixed_cow_array_map());
2706 DCHECK(index >= 0 && index < this->length());
2707 DCHECK(!GetHeap()->InNewSpace(GetHeap()->undefined_value()));
2708 WRITE_FIELD(this,
2709 kHeaderSize + index * kPointerSize,
2710 GetHeap()->undefined_value());
2711 }
2712
2713
set_null(int index)2714 void FixedArray::set_null(int index) {
2715 DCHECK(index >= 0 && index < this->length());
2716 DCHECK(!GetHeap()->InNewSpace(GetHeap()->null_value()));
2717 WRITE_FIELD(this,
2718 kHeaderSize + index * kPointerSize,
2719 GetHeap()->null_value());
2720 }
2721
2722
set_the_hole(int index)2723 void FixedArray::set_the_hole(int index) {
2724 DCHECK(map() != GetHeap()->fixed_cow_array_map());
2725 DCHECK(index >= 0 && index < this->length());
2726 DCHECK(!GetHeap()->InNewSpace(GetHeap()->the_hole_value()));
2727 WRITE_FIELD(this,
2728 kHeaderSize + index * kPointerSize,
2729 GetHeap()->the_hole_value());
2730 }
2731
2732
FillWithHoles(int from,int to)2733 void FixedArray::FillWithHoles(int from, int to) {
2734 for (int i = from; i < to; i++) {
2735 set_the_hole(i);
2736 }
2737 }
2738
2739
data_start()2740 Object** FixedArray::data_start() {
2741 return HeapObject::RawField(this, kHeaderSize);
2742 }
2743
2744
IsEmpty()2745 bool DescriptorArray::IsEmpty() {
2746 DCHECK(length() >= kFirstIndex ||
2747 this == GetHeap()->empty_descriptor_array());
2748 return length() < kFirstIndex;
2749 }
2750
2751
SetNumberOfDescriptors(int number_of_descriptors)2752 void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) {
2753 WRITE_FIELD(
2754 this, kDescriptorLengthOffset, Smi::FromInt(number_of_descriptors));
2755 }
2756
2757
2758 // Perform a binary search in a fixed array. Low and high are entry indices. If
2759 // there are three entries in this array it should be called with low=0 and
2760 // high=2.
2761 template<SearchMode search_mode, typename T>
BinarySearch(T * array,Name * name,int low,int high,int valid_entries)2762 int BinarySearch(T* array, Name* name, int low, int high, int valid_entries) {
2763 uint32_t hash = name->Hash();
2764 int limit = high;
2765
2766 DCHECK(low <= high);
2767
2768 while (low != high) {
2769 int mid = (low + high) / 2;
2770 Name* mid_name = array->GetSortedKey(mid);
2771 uint32_t mid_hash = mid_name->Hash();
2772
2773 if (mid_hash >= hash) {
2774 high = mid;
2775 } else {
2776 low = mid + 1;
2777 }
2778 }
2779
2780 for (; low <= limit; ++low) {
2781 int sort_index = array->GetSortedKeyIndex(low);
2782 Name* entry = array->GetKey(sort_index);
2783 if (entry->Hash() != hash) break;
2784 if (entry->Equals(name)) {
2785 if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
2786 return sort_index;
2787 }
2788 return T::kNotFound;
2789 }
2790 }
2791
2792 return T::kNotFound;
2793 }
2794
2795
2796 // Perform a linear search in this fixed array. len is the number of entry
2797 // indices that are valid.
2798 template<SearchMode search_mode, typename T>
LinearSearch(T * array,Name * name,int len,int valid_entries)2799 int LinearSearch(T* array, Name* name, int len, int valid_entries) {
2800 uint32_t hash = name->Hash();
2801 if (search_mode == ALL_ENTRIES) {
2802 for (int number = 0; number < len; number++) {
2803 int sorted_index = array->GetSortedKeyIndex(number);
2804 Name* entry = array->GetKey(sorted_index);
2805 uint32_t current_hash = entry->Hash();
2806 if (current_hash > hash) break;
2807 if (current_hash == hash && entry->Equals(name)) return sorted_index;
2808 }
2809 } else {
2810 DCHECK(len >= valid_entries);
2811 for (int number = 0; number < valid_entries; number++) {
2812 Name* entry = array->GetKey(number);
2813 uint32_t current_hash = entry->Hash();
2814 if (current_hash == hash && entry->Equals(name)) return number;
2815 }
2816 }
2817 return T::kNotFound;
2818 }
2819
2820
2821 template<SearchMode search_mode, typename T>
Search(T * array,Name * name,int valid_entries)2822 int Search(T* array, Name* name, int valid_entries) {
2823 if (search_mode == VALID_ENTRIES) {
2824 SLOW_DCHECK(array->IsSortedNoDuplicates(valid_entries));
2825 } else {
2826 SLOW_DCHECK(array->IsSortedNoDuplicates());
2827 }
2828
2829 int nof = array->number_of_entries();
2830 if (nof == 0) return T::kNotFound;
2831
2832 // Fast case: do linear search for small arrays.
2833 const int kMaxElementsForLinearSearch = 8;
2834 if ((search_mode == ALL_ENTRIES &&
2835 nof <= kMaxElementsForLinearSearch) ||
2836 (search_mode == VALID_ENTRIES &&
2837 valid_entries <= (kMaxElementsForLinearSearch * 3))) {
2838 return LinearSearch<search_mode>(array, name, nof, valid_entries);
2839 }
2840
2841 // Slow case: perform binary search.
2842 return BinarySearch<search_mode>(array, name, 0, nof - 1, valid_entries);
2843 }
2844
2845
Search(Name * name,int valid_descriptors)2846 int DescriptorArray::Search(Name* name, int valid_descriptors) {
2847 return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors);
2848 }
2849
2850
SearchWithCache(Name * name,Map * map)2851 int DescriptorArray::SearchWithCache(Name* name, Map* map) {
2852 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
2853 if (number_of_own_descriptors == 0) return kNotFound;
2854
2855 DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
2856 int number = cache->Lookup(map, name);
2857
2858 if (number == DescriptorLookupCache::kAbsent) {
2859 number = Search(name, number_of_own_descriptors);
2860 cache->Update(map, name, number);
2861 }
2862
2863 return number;
2864 }
2865
2866
GetLastDescriptorDetails()2867 PropertyDetails Map::GetLastDescriptorDetails() {
2868 return instance_descriptors()->GetDetails(LastAdded());
2869 }
2870
2871
LookupDescriptor(JSObject * holder,Name * name,LookupResult * result)2872 void Map::LookupDescriptor(JSObject* holder,
2873 Name* name,
2874 LookupResult* result) {
2875 DescriptorArray* descriptors = this->instance_descriptors();
2876 int number = descriptors->SearchWithCache(name, this);
2877 if (number == DescriptorArray::kNotFound) return result->NotFound();
2878 result->DescriptorResult(holder, descriptors->GetDetails(number), number);
2879 }
2880
2881
LookupTransition(JSObject * holder,Name * name,LookupResult * result)2882 void Map::LookupTransition(JSObject* holder,
2883 Name* name,
2884 LookupResult* result) {
2885 int transition_index = this->SearchTransition(name);
2886 if (transition_index == TransitionArray::kNotFound) return result->NotFound();
2887 result->TransitionResult(holder, this->GetTransition(transition_index));
2888 }
2889
2890
GetInitialElements()2891 FixedArrayBase* Map::GetInitialElements() {
2892 if (has_fast_smi_or_object_elements() ||
2893 has_fast_double_elements()) {
2894 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
2895 return GetHeap()->empty_fixed_array();
2896 } else if (has_external_array_elements()) {
2897 ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(this);
2898 DCHECK(!GetHeap()->InNewSpace(empty_array));
2899 return empty_array;
2900 } else if (has_fixed_typed_array_elements()) {
2901 FixedTypedArrayBase* empty_array =
2902 GetHeap()->EmptyFixedTypedArrayForMap(this);
2903 DCHECK(!GetHeap()->InNewSpace(empty_array));
2904 return empty_array;
2905 } else {
2906 UNREACHABLE();
2907 }
2908 return NULL;
2909 }
2910
2911
GetKeySlot(int descriptor_number)2912 Object** DescriptorArray::GetKeySlot(int descriptor_number) {
2913 DCHECK(descriptor_number < number_of_descriptors());
2914 return RawFieldOfElementAt(ToKeyIndex(descriptor_number));
2915 }
2916
2917
GetDescriptorStartSlot(int descriptor_number)2918 Object** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) {
2919 return GetKeySlot(descriptor_number);
2920 }
2921
2922
GetDescriptorEndSlot(int descriptor_number)2923 Object** DescriptorArray::GetDescriptorEndSlot(int descriptor_number) {
2924 return GetValueSlot(descriptor_number - 1) + 1;
2925 }
2926
2927
GetKey(int descriptor_number)2928 Name* DescriptorArray::GetKey(int descriptor_number) {
2929 DCHECK(descriptor_number < number_of_descriptors());
2930 return Name::cast(get(ToKeyIndex(descriptor_number)));
2931 }
2932
2933
GetSortedKeyIndex(int descriptor_number)2934 int DescriptorArray::GetSortedKeyIndex(int descriptor_number) {
2935 return GetDetails(descriptor_number).pointer();
2936 }
2937
2938
GetSortedKey(int descriptor_number)2939 Name* DescriptorArray::GetSortedKey(int descriptor_number) {
2940 return GetKey(GetSortedKeyIndex(descriptor_number));
2941 }
2942
2943
SetSortedKey(int descriptor_index,int pointer)2944 void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) {
2945 PropertyDetails details = GetDetails(descriptor_index);
2946 set(ToDetailsIndex(descriptor_index), details.set_pointer(pointer).AsSmi());
2947 }
2948
2949
SetRepresentation(int descriptor_index,Representation representation)2950 void DescriptorArray::SetRepresentation(int descriptor_index,
2951 Representation representation) {
2952 DCHECK(!representation.IsNone());
2953 PropertyDetails details = GetDetails(descriptor_index);
2954 set(ToDetailsIndex(descriptor_index),
2955 details.CopyWithRepresentation(representation).AsSmi());
2956 }
2957
2958
GetValueSlot(int descriptor_number)2959 Object** DescriptorArray::GetValueSlot(int descriptor_number) {
2960 DCHECK(descriptor_number < number_of_descriptors());
2961 return RawFieldOfElementAt(ToValueIndex(descriptor_number));
2962 }
2963
2964
GetValueOffset(int descriptor_number)2965 int DescriptorArray::GetValueOffset(int descriptor_number) {
2966 return OffsetOfElementAt(ToValueIndex(descriptor_number));
2967 }
2968
2969
GetValue(int descriptor_number)2970 Object* DescriptorArray::GetValue(int descriptor_number) {
2971 DCHECK(descriptor_number < number_of_descriptors());
2972 return get(ToValueIndex(descriptor_number));
2973 }
2974
2975
SetValue(int descriptor_index,Object * value)2976 void DescriptorArray::SetValue(int descriptor_index, Object* value) {
2977 set(ToValueIndex(descriptor_index), value);
2978 }
2979
2980
GetDetails(int descriptor_number)2981 PropertyDetails DescriptorArray::GetDetails(int descriptor_number) {
2982 DCHECK(descriptor_number < number_of_descriptors());
2983 Object* details = get(ToDetailsIndex(descriptor_number));
2984 return PropertyDetails(Smi::cast(details));
2985 }
2986
2987
GetType(int descriptor_number)2988 PropertyType DescriptorArray::GetType(int descriptor_number) {
2989 return GetDetails(descriptor_number).type();
2990 }
2991
2992
GetFieldIndex(int descriptor_number)2993 int DescriptorArray::GetFieldIndex(int descriptor_number) {
2994 DCHECK(GetDetails(descriptor_number).type() == FIELD);
2995 return GetDetails(descriptor_number).field_index();
2996 }
2997
2998
GetFieldType(int descriptor_number)2999 HeapType* DescriptorArray::GetFieldType(int descriptor_number) {
3000 DCHECK(GetDetails(descriptor_number).type() == FIELD);
3001 return HeapType::cast(GetValue(descriptor_number));
3002 }
3003
3004
GetConstant(int descriptor_number)3005 Object* DescriptorArray::GetConstant(int descriptor_number) {
3006 return GetValue(descriptor_number);
3007 }
3008
3009
GetCallbacksObject(int descriptor_number)3010 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
3011 DCHECK(GetType(descriptor_number) == CALLBACKS);
3012 return GetValue(descriptor_number);
3013 }
3014
3015
GetCallbacks(int descriptor_number)3016 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
3017 DCHECK(GetType(descriptor_number) == CALLBACKS);
3018 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number));
3019 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address());
3020 }
3021
3022
Get(int descriptor_number,Descriptor * desc)3023 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
3024 desc->Init(handle(GetKey(descriptor_number), GetIsolate()),
3025 handle(GetValue(descriptor_number), GetIsolate()),
3026 GetDetails(descriptor_number));
3027 }
3028
3029
Set(int descriptor_number,Descriptor * desc,const WhitenessWitness &)3030 void DescriptorArray::Set(int descriptor_number,
3031 Descriptor* desc,
3032 const WhitenessWitness&) {
3033 // Range check.
3034 DCHECK(descriptor_number < number_of_descriptors());
3035
3036 NoIncrementalWriteBarrierSet(this,
3037 ToKeyIndex(descriptor_number),
3038 *desc->GetKey());
3039 NoIncrementalWriteBarrierSet(this,
3040 ToValueIndex(descriptor_number),
3041 *desc->GetValue());
3042 NoIncrementalWriteBarrierSet(this,
3043 ToDetailsIndex(descriptor_number),
3044 desc->GetDetails().AsSmi());
3045 }
3046
3047
Set(int descriptor_number,Descriptor * desc)3048 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
3049 // Range check.
3050 DCHECK(descriptor_number < number_of_descriptors());
3051
3052 set(ToKeyIndex(descriptor_number), *desc->GetKey());
3053 set(ToValueIndex(descriptor_number), *desc->GetValue());
3054 set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi());
3055 }
3056
3057
Append(Descriptor * desc)3058 void DescriptorArray::Append(Descriptor* desc) {
3059 DisallowHeapAllocation no_gc;
3060 int descriptor_number = number_of_descriptors();
3061 SetNumberOfDescriptors(descriptor_number + 1);
3062 Set(descriptor_number, desc);
3063
3064 uint32_t hash = desc->GetKey()->Hash();
3065
3066 int insertion;
3067
3068 for (insertion = descriptor_number; insertion > 0; --insertion) {
3069 Name* key = GetSortedKey(insertion - 1);
3070 if (key->Hash() <= hash) break;
3071 SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
3072 }
3073
3074 SetSortedKey(insertion, descriptor_number);
3075 }
3076
3077
SwapSortedKeys(int first,int second)3078 void DescriptorArray::SwapSortedKeys(int first, int second) {
3079 int first_key = GetSortedKeyIndex(first);
3080 SetSortedKey(first, GetSortedKeyIndex(second));
3081 SetSortedKey(second, first_key);
3082 }
3083
3084
WhitenessWitness(DescriptorArray * array)3085 DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
3086 : marking_(array->GetHeap()->incremental_marking()) {
3087 marking_->EnterNoMarkingScope();
3088 DCHECK(!marking_->IsMarking() ||
3089 Marking::Color(array) == Marking::WHITE_OBJECT);
3090 }
3091
3092
~WhitenessWitness()3093 DescriptorArray::WhitenessWitness::~WhitenessWitness() {
3094 marking_->LeaveNoMarkingScope();
3095 }
3096
3097
3098 template<typename Derived, typename Shape, typename Key>
ComputeCapacity(int at_least_space_for)3099 int HashTable<Derived, Shape, Key>::ComputeCapacity(int at_least_space_for) {
3100 const int kMinCapacity = 32;
3101 int capacity = base::bits::RoundUpToPowerOfTwo32(at_least_space_for * 2);
3102 if (capacity < kMinCapacity) {
3103 capacity = kMinCapacity; // Guarantee min capacity.
3104 }
3105 return capacity;
3106 }
3107
3108
3109 template<typename Derived, typename Shape, typename Key>
FindEntry(Key key)3110 int HashTable<Derived, Shape, Key>::FindEntry(Key key) {
3111 return FindEntry(GetIsolate(), key);
3112 }
3113
3114
3115 // Find entry for key otherwise return kNotFound.
3116 template<typename Derived, typename Shape, typename Key>
FindEntry(Isolate * isolate,Key key)3117 int HashTable<Derived, Shape, Key>::FindEntry(Isolate* isolate, Key key) {
3118 uint32_t capacity = Capacity();
3119 uint32_t entry = FirstProbe(HashTable::Hash(key), capacity);
3120 uint32_t count = 1;
3121 // EnsureCapacity will guarantee the hash table is never full.
3122 while (true) {
3123 Object* element = KeyAt(entry);
3124 // Empty entry. Uses raw unchecked accessors because it is called by the
3125 // string table during bootstrapping.
3126 if (element == isolate->heap()->raw_unchecked_undefined_value()) break;
3127 if (element != isolate->heap()->raw_unchecked_the_hole_value() &&
3128 Shape::IsMatch(key, element)) return entry;
3129 entry = NextProbe(entry, count++, capacity);
3130 }
3131 return kNotFound;
3132 }
3133
3134
requires_slow_elements()3135 bool SeededNumberDictionary::requires_slow_elements() {
3136 Object* max_index_object = get(kMaxNumberKeyIndex);
3137 if (!max_index_object->IsSmi()) return false;
3138 return 0 !=
3139 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
3140 }
3141
max_number_key()3142 uint32_t SeededNumberDictionary::max_number_key() {
3143 DCHECK(!requires_slow_elements());
3144 Object* max_index_object = get(kMaxNumberKeyIndex);
3145 if (!max_index_object->IsSmi()) return 0;
3146 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
3147 return value >> kRequiresSlowElementsTagSize;
3148 }
3149
set_requires_slow_elements()3150 void SeededNumberDictionary::set_requires_slow_elements() {
3151 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
3152 }
3153
3154
3155 // ------------------------------------
3156 // Cast operations
3157
3158
3159 CAST_ACCESSOR(AccessorInfo)
CAST_ACCESSOR(ByteArray)3160 CAST_ACCESSOR(ByteArray)
3161 CAST_ACCESSOR(Cell)
3162 CAST_ACCESSOR(Code)
3163 CAST_ACCESSOR(CodeCacheHashTable)
3164 CAST_ACCESSOR(CompilationCacheTable)
3165 CAST_ACCESSOR(ConsString)
3166 CAST_ACCESSOR(ConstantPoolArray)
3167 CAST_ACCESSOR(DeoptimizationInputData)
3168 CAST_ACCESSOR(DeoptimizationOutputData)
3169 CAST_ACCESSOR(DependentCode)
3170 CAST_ACCESSOR(DescriptorArray)
3171 CAST_ACCESSOR(ExternalArray)
3172 CAST_ACCESSOR(ExternalOneByteString)
3173 CAST_ACCESSOR(ExternalFloat32Array)
3174 CAST_ACCESSOR(ExternalFloat64Array)
3175 CAST_ACCESSOR(ExternalInt16Array)
3176 CAST_ACCESSOR(ExternalInt32Array)
3177 CAST_ACCESSOR(ExternalInt8Array)
3178 CAST_ACCESSOR(ExternalString)
3179 CAST_ACCESSOR(ExternalTwoByteString)
3180 CAST_ACCESSOR(ExternalUint16Array)
3181 CAST_ACCESSOR(ExternalUint32Array)
3182 CAST_ACCESSOR(ExternalUint8Array)
3183 CAST_ACCESSOR(ExternalUint8ClampedArray)
3184 CAST_ACCESSOR(FixedArray)
3185 CAST_ACCESSOR(FixedArrayBase)
3186 CAST_ACCESSOR(FixedDoubleArray)
3187 CAST_ACCESSOR(FixedTypedArrayBase)
3188 CAST_ACCESSOR(Foreign)
3189 CAST_ACCESSOR(FreeSpace)
3190 CAST_ACCESSOR(GlobalObject)
3191 CAST_ACCESSOR(HeapObject)
3192 CAST_ACCESSOR(JSArray)
3193 CAST_ACCESSOR(JSArrayBuffer)
3194 CAST_ACCESSOR(JSArrayBufferView)
3195 CAST_ACCESSOR(JSBuiltinsObject)
3196 CAST_ACCESSOR(JSDataView)
3197 CAST_ACCESSOR(JSDate)
3198 CAST_ACCESSOR(JSFunction)
3199 CAST_ACCESSOR(JSFunctionProxy)
3200 CAST_ACCESSOR(JSFunctionResultCache)
3201 CAST_ACCESSOR(JSGeneratorObject)
3202 CAST_ACCESSOR(JSGlobalObject)
3203 CAST_ACCESSOR(JSGlobalProxy)
3204 CAST_ACCESSOR(JSMap)
3205 CAST_ACCESSOR(JSMapIterator)
3206 CAST_ACCESSOR(JSMessageObject)
3207 CAST_ACCESSOR(JSModule)
3208 CAST_ACCESSOR(JSObject)
3209 CAST_ACCESSOR(JSProxy)
3210 CAST_ACCESSOR(JSReceiver)
3211 CAST_ACCESSOR(JSRegExp)
3212 CAST_ACCESSOR(JSSet)
3213 CAST_ACCESSOR(JSSetIterator)
3214 CAST_ACCESSOR(JSTypedArray)
3215 CAST_ACCESSOR(JSValue)
3216 CAST_ACCESSOR(JSWeakMap)
3217 CAST_ACCESSOR(JSWeakSet)
3218 CAST_ACCESSOR(Map)
3219 CAST_ACCESSOR(MapCache)
3220 CAST_ACCESSOR(Name)
3221 CAST_ACCESSOR(NameDictionary)
3222 CAST_ACCESSOR(NormalizedMapCache)
3223 CAST_ACCESSOR(Object)
3224 CAST_ACCESSOR(ObjectHashTable)
3225 CAST_ACCESSOR(Oddball)
3226 CAST_ACCESSOR(OrderedHashMap)
3227 CAST_ACCESSOR(OrderedHashSet)
3228 CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
3229 CAST_ACCESSOR(PropertyCell)
3230 CAST_ACCESSOR(ScopeInfo)
3231 CAST_ACCESSOR(SeededNumberDictionary)
3232 CAST_ACCESSOR(SeqOneByteString)
3233 CAST_ACCESSOR(SeqString)
3234 CAST_ACCESSOR(SeqTwoByteString)
3235 CAST_ACCESSOR(SharedFunctionInfo)
3236 CAST_ACCESSOR(SlicedString)
3237 CAST_ACCESSOR(Smi)
3238 CAST_ACCESSOR(String)
3239 CAST_ACCESSOR(StringTable)
3240 CAST_ACCESSOR(Struct)
3241 CAST_ACCESSOR(Symbol)
3242 CAST_ACCESSOR(UnseededNumberDictionary)
3243 CAST_ACCESSOR(WeakHashTable)
3244
3245
3246 template <class Traits>
3247 FixedTypedArray<Traits>* FixedTypedArray<Traits>::cast(Object* object) {
3248 SLOW_DCHECK(object->IsHeapObject() &&
3249 HeapObject::cast(object)->map()->instance_type() ==
3250 Traits::kInstanceType);
3251 return reinterpret_cast<FixedTypedArray<Traits>*>(object);
3252 }
3253
3254
3255 template <class Traits>
3256 const FixedTypedArray<Traits>*
cast(const Object * object)3257 FixedTypedArray<Traits>::cast(const Object* object) {
3258 SLOW_DCHECK(object->IsHeapObject() &&
3259 HeapObject::cast(object)->map()->instance_type() ==
3260 Traits::kInstanceType);
3261 return reinterpret_cast<FixedTypedArray<Traits>*>(object);
3262 }
3263
3264
3265 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
STRUCT_LIST(MAKE_STRUCT_CAST)3266 STRUCT_LIST(MAKE_STRUCT_CAST)
3267 #undef MAKE_STRUCT_CAST
3268
3269
3270 template <typename Derived, typename Shape, typename Key>
3271 HashTable<Derived, Shape, Key>*
3272 HashTable<Derived, Shape, Key>::cast(Object* obj) {
3273 SLOW_DCHECK(obj->IsHashTable());
3274 return reinterpret_cast<HashTable*>(obj);
3275 }
3276
3277
3278 template <typename Derived, typename Shape, typename Key>
3279 const HashTable<Derived, Shape, Key>*
cast(const Object * obj)3280 HashTable<Derived, Shape, Key>::cast(const Object* obj) {
3281 SLOW_DCHECK(obj->IsHashTable());
3282 return reinterpret_cast<const HashTable*>(obj);
3283 }
3284
3285
SMI_ACCESSORS(FixedArrayBase,length,kLengthOffset)3286 SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
3287 SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
3288
3289 SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
3290 NOBARRIER_SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
3291
3292 SMI_ACCESSORS(String, length, kLengthOffset)
3293 SYNCHRONIZED_SMI_ACCESSORS(String, length, kLengthOffset)
3294
3295
3296 uint32_t Name::hash_field() {
3297 return READ_UINT32_FIELD(this, kHashFieldOffset);
3298 }
3299
3300
set_hash_field(uint32_t value)3301 void Name::set_hash_field(uint32_t value) {
3302 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
3303 #if V8_HOST_ARCH_64_BIT
3304 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
3305 #endif
3306 }
3307
3308
Equals(Name * other)3309 bool Name::Equals(Name* other) {
3310 if (other == this) return true;
3311 if ((this->IsInternalizedString() && other->IsInternalizedString()) ||
3312 this->IsSymbol() || other->IsSymbol()) {
3313 return false;
3314 }
3315 return String::cast(this)->SlowEquals(String::cast(other));
3316 }
3317
3318
Equals(Handle<Name> one,Handle<Name> two)3319 bool Name::Equals(Handle<Name> one, Handle<Name> two) {
3320 if (one.is_identical_to(two)) return true;
3321 if ((one->IsInternalizedString() && two->IsInternalizedString()) ||
3322 one->IsSymbol() || two->IsSymbol()) {
3323 return false;
3324 }
3325 return String::SlowEquals(Handle<String>::cast(one),
3326 Handle<String>::cast(two));
3327 }
3328
3329
ACCESSORS(Symbol,name,Object,kNameOffset)3330 ACCESSORS(Symbol, name, Object, kNameOffset)
3331 ACCESSORS(Symbol, flags, Smi, kFlagsOffset)
3332 BOOL_ACCESSORS(Symbol, flags, is_private, kPrivateBit)
3333 BOOL_ACCESSORS(Symbol, flags, is_own, kOwnBit)
3334
3335
3336 bool String::Equals(String* other) {
3337 if (other == this) return true;
3338 if (this->IsInternalizedString() && other->IsInternalizedString()) {
3339 return false;
3340 }
3341 return SlowEquals(other);
3342 }
3343
3344
Equals(Handle<String> one,Handle<String> two)3345 bool String::Equals(Handle<String> one, Handle<String> two) {
3346 if (one.is_identical_to(two)) return true;
3347 if (one->IsInternalizedString() && two->IsInternalizedString()) {
3348 return false;
3349 }
3350 return SlowEquals(one, two);
3351 }
3352
3353
Flatten(Handle<String> string,PretenureFlag pretenure)3354 Handle<String> String::Flatten(Handle<String> string, PretenureFlag pretenure) {
3355 if (!string->IsConsString()) return string;
3356 Handle<ConsString> cons = Handle<ConsString>::cast(string);
3357 if (cons->IsFlat()) return handle(cons->first());
3358 return SlowFlatten(cons, pretenure);
3359 }
3360
3361
Get(int index)3362 uint16_t String::Get(int index) {
3363 DCHECK(index >= 0 && index < length());
3364 switch (StringShape(this).full_representation_tag()) {
3365 case kSeqStringTag | kOneByteStringTag:
3366 return SeqOneByteString::cast(this)->SeqOneByteStringGet(index);
3367 case kSeqStringTag | kTwoByteStringTag:
3368 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
3369 case kConsStringTag | kOneByteStringTag:
3370 case kConsStringTag | kTwoByteStringTag:
3371 return ConsString::cast(this)->ConsStringGet(index);
3372 case kExternalStringTag | kOneByteStringTag:
3373 return ExternalOneByteString::cast(this)->ExternalOneByteStringGet(index);
3374 case kExternalStringTag | kTwoByteStringTag:
3375 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
3376 case kSlicedStringTag | kOneByteStringTag:
3377 case kSlicedStringTag | kTwoByteStringTag:
3378 return SlicedString::cast(this)->SlicedStringGet(index);
3379 default:
3380 break;
3381 }
3382
3383 UNREACHABLE();
3384 return 0;
3385 }
3386
3387
Set(int index,uint16_t value)3388 void String::Set(int index, uint16_t value) {
3389 DCHECK(index >= 0 && index < length());
3390 DCHECK(StringShape(this).IsSequential());
3391
3392 return this->IsOneByteRepresentation()
3393 ? SeqOneByteString::cast(this)->SeqOneByteStringSet(index, value)
3394 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
3395 }
3396
3397
IsFlat()3398 bool String::IsFlat() {
3399 if (!StringShape(this).IsCons()) return true;
3400 return ConsString::cast(this)->second()->length() == 0;
3401 }
3402
3403
GetUnderlying()3404 String* String::GetUnderlying() {
3405 // Giving direct access to underlying string only makes sense if the
3406 // wrapping string is already flattened.
3407 DCHECK(this->IsFlat());
3408 DCHECK(StringShape(this).IsIndirect());
3409 STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
3410 const int kUnderlyingOffset = SlicedString::kParentOffset;
3411 return String::cast(READ_FIELD(this, kUnderlyingOffset));
3412 }
3413
3414
3415 template<class Visitor>
VisitFlat(Visitor * visitor,String * string,const int offset)3416 ConsString* String::VisitFlat(Visitor* visitor,
3417 String* string,
3418 const int offset) {
3419 int slice_offset = offset;
3420 const int length = string->length();
3421 DCHECK(offset <= length);
3422 while (true) {
3423 int32_t type = string->map()->instance_type();
3424 switch (type & (kStringRepresentationMask | kStringEncodingMask)) {
3425 case kSeqStringTag | kOneByteStringTag:
3426 visitor->VisitOneByteString(
3427 SeqOneByteString::cast(string)->GetChars() + slice_offset,
3428 length - offset);
3429 return NULL;
3430
3431 case kSeqStringTag | kTwoByteStringTag:
3432 visitor->VisitTwoByteString(
3433 SeqTwoByteString::cast(string)->GetChars() + slice_offset,
3434 length - offset);
3435 return NULL;
3436
3437 case kExternalStringTag | kOneByteStringTag:
3438 visitor->VisitOneByteString(
3439 ExternalOneByteString::cast(string)->GetChars() + slice_offset,
3440 length - offset);
3441 return NULL;
3442
3443 case kExternalStringTag | kTwoByteStringTag:
3444 visitor->VisitTwoByteString(
3445 ExternalTwoByteString::cast(string)->GetChars() + slice_offset,
3446 length - offset);
3447 return NULL;
3448
3449 case kSlicedStringTag | kOneByteStringTag:
3450 case kSlicedStringTag | kTwoByteStringTag: {
3451 SlicedString* slicedString = SlicedString::cast(string);
3452 slice_offset += slicedString->offset();
3453 string = slicedString->parent();
3454 continue;
3455 }
3456
3457 case kConsStringTag | kOneByteStringTag:
3458 case kConsStringTag | kTwoByteStringTag:
3459 return ConsString::cast(string);
3460
3461 default:
3462 UNREACHABLE();
3463 return NULL;
3464 }
3465 }
3466 }
3467
3468
SeqOneByteStringGet(int index)3469 uint16_t SeqOneByteString::SeqOneByteStringGet(int index) {
3470 DCHECK(index >= 0 && index < length());
3471 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
3472 }
3473
3474
SeqOneByteStringSet(int index,uint16_t value)3475 void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) {
3476 DCHECK(index >= 0 && index < length() && value <= kMaxOneByteCharCode);
3477 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
3478 static_cast<byte>(value));
3479 }
3480
3481
GetCharsAddress()3482 Address SeqOneByteString::GetCharsAddress() {
3483 return FIELD_ADDR(this, kHeaderSize);
3484 }
3485
3486
GetChars()3487 uint8_t* SeqOneByteString::GetChars() {
3488 return reinterpret_cast<uint8_t*>(GetCharsAddress());
3489 }
3490
3491
GetCharsAddress()3492 Address SeqTwoByteString::GetCharsAddress() {
3493 return FIELD_ADDR(this, kHeaderSize);
3494 }
3495
3496
GetChars()3497 uc16* SeqTwoByteString::GetChars() {
3498 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
3499 }
3500
3501
SeqTwoByteStringGet(int index)3502 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
3503 DCHECK(index >= 0 && index < length());
3504 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
3505 }
3506
3507
SeqTwoByteStringSet(int index,uint16_t value)3508 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
3509 DCHECK(index >= 0 && index < length());
3510 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
3511 }
3512
3513
SeqTwoByteStringSize(InstanceType instance_type)3514 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
3515 return SizeFor(length());
3516 }
3517
3518
SeqOneByteStringSize(InstanceType instance_type)3519 int SeqOneByteString::SeqOneByteStringSize(InstanceType instance_type) {
3520 return SizeFor(length());
3521 }
3522
3523
parent()3524 String* SlicedString::parent() {
3525 return String::cast(READ_FIELD(this, kParentOffset));
3526 }
3527
3528
set_parent(String * parent,WriteBarrierMode mode)3529 void SlicedString::set_parent(String* parent, WriteBarrierMode mode) {
3530 DCHECK(parent->IsSeqString() || parent->IsExternalString());
3531 WRITE_FIELD(this, kParentOffset, parent);
3532 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kParentOffset, parent, mode);
3533 }
3534
3535
SMI_ACCESSORS(SlicedString,offset,kOffsetOffset)3536 SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
3537
3538
3539 String* ConsString::first() {
3540 return String::cast(READ_FIELD(this, kFirstOffset));
3541 }
3542
3543
unchecked_first()3544 Object* ConsString::unchecked_first() {
3545 return READ_FIELD(this, kFirstOffset);
3546 }
3547
3548
set_first(String * value,WriteBarrierMode mode)3549 void ConsString::set_first(String* value, WriteBarrierMode mode) {
3550 WRITE_FIELD(this, kFirstOffset, value);
3551 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode);
3552 }
3553
3554
second()3555 String* ConsString::second() {
3556 return String::cast(READ_FIELD(this, kSecondOffset));
3557 }
3558
3559
unchecked_second()3560 Object* ConsString::unchecked_second() {
3561 return READ_FIELD(this, kSecondOffset);
3562 }
3563
3564
set_second(String * value,WriteBarrierMode mode)3565 void ConsString::set_second(String* value, WriteBarrierMode mode) {
3566 WRITE_FIELD(this, kSecondOffset, value);
3567 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode);
3568 }
3569
3570
is_short()3571 bool ExternalString::is_short() {
3572 InstanceType type = map()->instance_type();
3573 return (type & kShortExternalStringMask) == kShortExternalStringTag;
3574 }
3575
3576
resource()3577 const ExternalOneByteString::Resource* ExternalOneByteString::resource() {
3578 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
3579 }
3580
3581
update_data_cache()3582 void ExternalOneByteString::update_data_cache() {
3583 if (is_short()) return;
3584 const char** data_field =
3585 reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset));
3586 *data_field = resource()->data();
3587 }
3588
3589
set_resource(const ExternalOneByteString::Resource * resource)3590 void ExternalOneByteString::set_resource(
3591 const ExternalOneByteString::Resource* resource) {
3592 DCHECK(IsAligned(reinterpret_cast<intptr_t>(resource), kPointerSize));
3593 *reinterpret_cast<const Resource**>(
3594 FIELD_ADDR(this, kResourceOffset)) = resource;
3595 if (resource != NULL) update_data_cache();
3596 }
3597
3598
GetChars()3599 const uint8_t* ExternalOneByteString::GetChars() {
3600 return reinterpret_cast<const uint8_t*>(resource()->data());
3601 }
3602
3603
ExternalOneByteStringGet(int index)3604 uint16_t ExternalOneByteString::ExternalOneByteStringGet(int index) {
3605 DCHECK(index >= 0 && index < length());
3606 return GetChars()[index];
3607 }
3608
3609
resource()3610 const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
3611 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
3612 }
3613
3614
update_data_cache()3615 void ExternalTwoByteString::update_data_cache() {
3616 if (is_short()) return;
3617 const uint16_t** data_field =
3618 reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset));
3619 *data_field = resource()->data();
3620 }
3621
3622
set_resource(const ExternalTwoByteString::Resource * resource)3623 void ExternalTwoByteString::set_resource(
3624 const ExternalTwoByteString::Resource* resource) {
3625 *reinterpret_cast<const Resource**>(
3626 FIELD_ADDR(this, kResourceOffset)) = resource;
3627 if (resource != NULL) update_data_cache();
3628 }
3629
3630
GetChars()3631 const uint16_t* ExternalTwoByteString::GetChars() {
3632 return resource()->data();
3633 }
3634
3635
ExternalTwoByteStringGet(int index)3636 uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
3637 DCHECK(index >= 0 && index < length());
3638 return GetChars()[index];
3639 }
3640
3641
ExternalTwoByteStringGetData(unsigned start)3642 const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
3643 unsigned start) {
3644 return GetChars() + start;
3645 }
3646
3647
OffsetForDepth(int depth)3648 int ConsStringIteratorOp::OffsetForDepth(int depth) {
3649 return depth & kDepthMask;
3650 }
3651
3652
PushLeft(ConsString * string)3653 void ConsStringIteratorOp::PushLeft(ConsString* string) {
3654 frames_[depth_++ & kDepthMask] = string;
3655 }
3656
3657
PushRight(ConsString * string)3658 void ConsStringIteratorOp::PushRight(ConsString* string) {
3659 // Inplace update.
3660 frames_[(depth_-1) & kDepthMask] = string;
3661 }
3662
3663
AdjustMaximumDepth()3664 void ConsStringIteratorOp::AdjustMaximumDepth() {
3665 if (depth_ > maximum_depth_) maximum_depth_ = depth_;
3666 }
3667
3668
Pop()3669 void ConsStringIteratorOp::Pop() {
3670 DCHECK(depth_ > 0);
3671 DCHECK(depth_ <= maximum_depth_);
3672 depth_--;
3673 }
3674
3675
GetNext()3676 uint16_t StringCharacterStream::GetNext() {
3677 DCHECK(buffer8_ != NULL && end_ != NULL);
3678 // Advance cursor if needed.
3679 if (buffer8_ == end_) HasMore();
3680 DCHECK(buffer8_ < end_);
3681 return is_one_byte_ ? *buffer8_++ : *buffer16_++;
3682 }
3683
3684
StringCharacterStream(String * string,ConsStringIteratorOp * op,int offset)3685 StringCharacterStream::StringCharacterStream(String* string,
3686 ConsStringIteratorOp* op,
3687 int offset)
3688 : is_one_byte_(false),
3689 op_(op) {
3690 Reset(string, offset);
3691 }
3692
3693
Reset(String * string,int offset)3694 void StringCharacterStream::Reset(String* string, int offset) {
3695 buffer8_ = NULL;
3696 end_ = NULL;
3697 ConsString* cons_string = String::VisitFlat(this, string, offset);
3698 op_->Reset(cons_string, offset);
3699 if (cons_string != NULL) {
3700 string = op_->Next(&offset);
3701 if (string != NULL) String::VisitFlat(this, string, offset);
3702 }
3703 }
3704
3705
HasMore()3706 bool StringCharacterStream::HasMore() {
3707 if (buffer8_ != end_) return true;
3708 int offset;
3709 String* string = op_->Next(&offset);
3710 DCHECK_EQ(offset, 0);
3711 if (string == NULL) return false;
3712 String::VisitFlat(this, string);
3713 DCHECK(buffer8_ != end_);
3714 return true;
3715 }
3716
3717
VisitOneByteString(const uint8_t * chars,int length)3718 void StringCharacterStream::VisitOneByteString(
3719 const uint8_t* chars, int length) {
3720 is_one_byte_ = true;
3721 buffer8_ = chars;
3722 end_ = chars + length;
3723 }
3724
3725
VisitTwoByteString(const uint16_t * chars,int length)3726 void StringCharacterStream::VisitTwoByteString(
3727 const uint16_t* chars, int length) {
3728 is_one_byte_ = false;
3729 buffer16_ = chars;
3730 end_ = reinterpret_cast<const uint8_t*>(chars + length);
3731 }
3732
3733
MakeZeroSize()3734 void JSFunctionResultCache::MakeZeroSize() {
3735 set_finger_index(kEntriesIndex);
3736 set_size(kEntriesIndex);
3737 }
3738
3739
Clear()3740 void JSFunctionResultCache::Clear() {
3741 int cache_size = size();
3742 Object** entries_start = RawFieldOfElementAt(kEntriesIndex);
3743 MemsetPointer(entries_start,
3744 GetHeap()->the_hole_value(),
3745 cache_size - kEntriesIndex);
3746 MakeZeroSize();
3747 }
3748
3749
size()3750 int JSFunctionResultCache::size() {
3751 return Smi::cast(get(kCacheSizeIndex))->value();
3752 }
3753
3754
set_size(int size)3755 void JSFunctionResultCache::set_size(int size) {
3756 set(kCacheSizeIndex, Smi::FromInt(size));
3757 }
3758
3759
finger_index()3760 int JSFunctionResultCache::finger_index() {
3761 return Smi::cast(get(kFingerIndex))->value();
3762 }
3763
3764
set_finger_index(int finger_index)3765 void JSFunctionResultCache::set_finger_index(int finger_index) {
3766 set(kFingerIndex, Smi::FromInt(finger_index));
3767 }
3768
3769
get(int index)3770 byte ByteArray::get(int index) {
3771 DCHECK(index >= 0 && index < this->length());
3772 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
3773 }
3774
3775
set(int index,byte value)3776 void ByteArray::set(int index, byte value) {
3777 DCHECK(index >= 0 && index < this->length());
3778 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
3779 }
3780
3781
get_int(int index)3782 int ByteArray::get_int(int index) {
3783 DCHECK(index >= 0 && (index * kIntSize) < this->length());
3784 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
3785 }
3786
3787
FromDataStartAddress(Address address)3788 ByteArray* ByteArray::FromDataStartAddress(Address address) {
3789 DCHECK_TAG_ALIGNED(address);
3790 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
3791 }
3792
3793
GetDataStartAddress()3794 Address ByteArray::GetDataStartAddress() {
3795 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
3796 }
3797
3798
external_uint8_clamped_pointer()3799 uint8_t* ExternalUint8ClampedArray::external_uint8_clamped_pointer() {
3800 return reinterpret_cast<uint8_t*>(external_pointer());
3801 }
3802
3803
get_scalar(int index)3804 uint8_t ExternalUint8ClampedArray::get_scalar(int index) {
3805 DCHECK((index >= 0) && (index < this->length()));
3806 uint8_t* ptr = external_uint8_clamped_pointer();
3807 return ptr[index];
3808 }
3809
3810
get(Handle<ExternalUint8ClampedArray> array,int index)3811 Handle<Object> ExternalUint8ClampedArray::get(
3812 Handle<ExternalUint8ClampedArray> array,
3813 int index) {
3814 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
3815 array->GetIsolate());
3816 }
3817
3818
set(int index,uint8_t value)3819 void ExternalUint8ClampedArray::set(int index, uint8_t value) {
3820 DCHECK((index >= 0) && (index < this->length()));
3821 uint8_t* ptr = external_uint8_clamped_pointer();
3822 ptr[index] = value;
3823 }
3824
3825
external_pointer()3826 void* ExternalArray::external_pointer() const {
3827 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
3828 return reinterpret_cast<void*>(ptr);
3829 }
3830
3831
set_external_pointer(void * value,WriteBarrierMode mode)3832 void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
3833 intptr_t ptr = reinterpret_cast<intptr_t>(value);
3834 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
3835 }
3836
3837
get_scalar(int index)3838 int8_t ExternalInt8Array::get_scalar(int index) {
3839 DCHECK((index >= 0) && (index < this->length()));
3840 int8_t* ptr = static_cast<int8_t*>(external_pointer());
3841 return ptr[index];
3842 }
3843
3844
get(Handle<ExternalInt8Array> array,int index)3845 Handle<Object> ExternalInt8Array::get(Handle<ExternalInt8Array> array,
3846 int index) {
3847 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
3848 array->GetIsolate());
3849 }
3850
3851
set(int index,int8_t value)3852 void ExternalInt8Array::set(int index, int8_t value) {
3853 DCHECK((index >= 0) && (index < this->length()));
3854 int8_t* ptr = static_cast<int8_t*>(external_pointer());
3855 ptr[index] = value;
3856 }
3857
3858
get_scalar(int index)3859 uint8_t ExternalUint8Array::get_scalar(int index) {
3860 DCHECK((index >= 0) && (index < this->length()));
3861 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
3862 return ptr[index];
3863 }
3864
3865
get(Handle<ExternalUint8Array> array,int index)3866 Handle<Object> ExternalUint8Array::get(Handle<ExternalUint8Array> array,
3867 int index) {
3868 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
3869 array->GetIsolate());
3870 }
3871
3872
set(int index,uint8_t value)3873 void ExternalUint8Array::set(int index, uint8_t value) {
3874 DCHECK((index >= 0) && (index < this->length()));
3875 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
3876 ptr[index] = value;
3877 }
3878
3879
get_scalar(int index)3880 int16_t ExternalInt16Array::get_scalar(int index) {
3881 DCHECK((index >= 0) && (index < this->length()));
3882 int16_t* ptr = static_cast<int16_t*>(external_pointer());
3883 return ptr[index];
3884 }
3885
3886
get(Handle<ExternalInt16Array> array,int index)3887 Handle<Object> ExternalInt16Array::get(Handle<ExternalInt16Array> array,
3888 int index) {
3889 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
3890 array->GetIsolate());
3891 }
3892
3893
set(int index,int16_t value)3894 void ExternalInt16Array::set(int index, int16_t value) {
3895 DCHECK((index >= 0) && (index < this->length()));
3896 int16_t* ptr = static_cast<int16_t*>(external_pointer());
3897 ptr[index] = value;
3898 }
3899
3900
get_scalar(int index)3901 uint16_t ExternalUint16Array::get_scalar(int index) {
3902 DCHECK((index >= 0) && (index < this->length()));
3903 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
3904 return ptr[index];
3905 }
3906
3907
get(Handle<ExternalUint16Array> array,int index)3908 Handle<Object> ExternalUint16Array::get(Handle<ExternalUint16Array> array,
3909 int index) {
3910 return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
3911 array->GetIsolate());
3912 }
3913
3914
set(int index,uint16_t value)3915 void ExternalUint16Array::set(int index, uint16_t value) {
3916 DCHECK((index >= 0) && (index < this->length()));
3917 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
3918 ptr[index] = value;
3919 }
3920
3921
get_scalar(int index)3922 int32_t ExternalInt32Array::get_scalar(int index) {
3923 DCHECK((index >= 0) && (index < this->length()));
3924 int32_t* ptr = static_cast<int32_t*>(external_pointer());
3925 return ptr[index];
3926 }
3927
3928
get(Handle<ExternalInt32Array> array,int index)3929 Handle<Object> ExternalInt32Array::get(Handle<ExternalInt32Array> array,
3930 int index) {
3931 return array->GetIsolate()->factory()->
3932 NewNumberFromInt(array->get_scalar(index));
3933 }
3934
3935
set(int index,int32_t value)3936 void ExternalInt32Array::set(int index, int32_t value) {
3937 DCHECK((index >= 0) && (index < this->length()));
3938 int32_t* ptr = static_cast<int32_t*>(external_pointer());
3939 ptr[index] = value;
3940 }
3941
3942
get_scalar(int index)3943 uint32_t ExternalUint32Array::get_scalar(int index) {
3944 DCHECK((index >= 0) && (index < this->length()));
3945 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
3946 return ptr[index];
3947 }
3948
3949
get(Handle<ExternalUint32Array> array,int index)3950 Handle<Object> ExternalUint32Array::get(Handle<ExternalUint32Array> array,
3951 int index) {
3952 return array->GetIsolate()->factory()->
3953 NewNumberFromUint(array->get_scalar(index));
3954 }
3955
3956
set(int index,uint32_t value)3957 void ExternalUint32Array::set(int index, uint32_t value) {
3958 DCHECK((index >= 0) && (index < this->length()));
3959 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
3960 ptr[index] = value;
3961 }
3962
3963
get_scalar(int index)3964 float ExternalFloat32Array::get_scalar(int index) {
3965 DCHECK((index >= 0) && (index < this->length()));
3966 float* ptr = static_cast<float*>(external_pointer());
3967 return ptr[index];
3968 }
3969
3970
get(Handle<ExternalFloat32Array> array,int index)3971 Handle<Object> ExternalFloat32Array::get(Handle<ExternalFloat32Array> array,
3972 int index) {
3973 return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index));
3974 }
3975
3976
set(int index,float value)3977 void ExternalFloat32Array::set(int index, float value) {
3978 DCHECK((index >= 0) && (index < this->length()));
3979 float* ptr = static_cast<float*>(external_pointer());
3980 ptr[index] = value;
3981 }
3982
3983
get_scalar(int index)3984 double ExternalFloat64Array::get_scalar(int index) {
3985 DCHECK((index >= 0) && (index < this->length()));
3986 double* ptr = static_cast<double*>(external_pointer());
3987 return ptr[index];
3988 }
3989
3990
get(Handle<ExternalFloat64Array> array,int index)3991 Handle<Object> ExternalFloat64Array::get(Handle<ExternalFloat64Array> array,
3992 int index) {
3993 return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index));
3994 }
3995
3996
set(int index,double value)3997 void ExternalFloat64Array::set(int index, double value) {
3998 DCHECK((index >= 0) && (index < this->length()));
3999 double* ptr = static_cast<double*>(external_pointer());
4000 ptr[index] = value;
4001 }
4002
4003
DataPtr()4004 void* FixedTypedArrayBase::DataPtr() {
4005 return FIELD_ADDR(this, kDataOffset);
4006 }
4007
4008
DataSize(InstanceType type)4009 int FixedTypedArrayBase::DataSize(InstanceType type) {
4010 int element_size;
4011 switch (type) {
4012 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
4013 case FIXED_##TYPE##_ARRAY_TYPE: \
4014 element_size = size; \
4015 break;
4016
4017 TYPED_ARRAYS(TYPED_ARRAY_CASE)
4018 #undef TYPED_ARRAY_CASE
4019 default:
4020 UNREACHABLE();
4021 return 0;
4022 }
4023 return length() * element_size;
4024 }
4025
4026
DataSize()4027 int FixedTypedArrayBase::DataSize() {
4028 return DataSize(map()->instance_type());
4029 }
4030
4031
size()4032 int FixedTypedArrayBase::size() {
4033 return OBJECT_POINTER_ALIGN(kDataOffset + DataSize());
4034 }
4035
4036
TypedArraySize(InstanceType type)4037 int FixedTypedArrayBase::TypedArraySize(InstanceType type) {
4038 return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type));
4039 }
4040
4041
defaultValue()4042 uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
4043
4044
defaultValue()4045 uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; }
4046
4047
defaultValue()4048 int8_t Int8ArrayTraits::defaultValue() { return 0; }
4049
4050
defaultValue()4051 uint16_t Uint16ArrayTraits::defaultValue() { return 0; }
4052
4053
defaultValue()4054 int16_t Int16ArrayTraits::defaultValue() { return 0; }
4055
4056
defaultValue()4057 uint32_t Uint32ArrayTraits::defaultValue() { return 0; }
4058
4059
defaultValue()4060 int32_t Int32ArrayTraits::defaultValue() { return 0; }
4061
4062
defaultValue()4063 float Float32ArrayTraits::defaultValue() {
4064 return static_cast<float>(base::OS::nan_value());
4065 }
4066
4067
defaultValue()4068 double Float64ArrayTraits::defaultValue() { return base::OS::nan_value(); }
4069
4070
4071 template <class Traits>
get_scalar(int index)4072 typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
4073 DCHECK((index >= 0) && (index < this->length()));
4074 ElementType* ptr = reinterpret_cast<ElementType*>(
4075 FIELD_ADDR(this, kDataOffset));
4076 return ptr[index];
4077 }
4078
4079
4080 template<> inline
4081 FixedTypedArray<Float64ArrayTraits>::ElementType
get_scalar(int index)4082 FixedTypedArray<Float64ArrayTraits>::get_scalar(int index) {
4083 DCHECK((index >= 0) && (index < this->length()));
4084 return READ_DOUBLE_FIELD(this, ElementOffset(index));
4085 }
4086
4087
4088 template <class Traits>
set(int index,ElementType value)4089 void FixedTypedArray<Traits>::set(int index, ElementType value) {
4090 DCHECK((index >= 0) && (index < this->length()));
4091 ElementType* ptr = reinterpret_cast<ElementType*>(
4092 FIELD_ADDR(this, kDataOffset));
4093 ptr[index] = value;
4094 }
4095
4096
4097 template<> inline
set(int index,Float64ArrayTraits::ElementType value)4098 void FixedTypedArray<Float64ArrayTraits>::set(
4099 int index, Float64ArrayTraits::ElementType value) {
4100 DCHECK((index >= 0) && (index < this->length()));
4101 WRITE_DOUBLE_FIELD(this, ElementOffset(index), value);
4102 }
4103
4104
4105 template <class Traits>
from_int(int value)4106 typename Traits::ElementType FixedTypedArray<Traits>::from_int(int value) {
4107 return static_cast<ElementType>(value);
4108 }
4109
4110
4111 template <> inline
from_int(int value)4112 uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from_int(int value) {
4113 if (value < 0) return 0;
4114 if (value > 0xFF) return 0xFF;
4115 return static_cast<uint8_t>(value);
4116 }
4117
4118
4119 template <class Traits>
from_double(double value)4120 typename Traits::ElementType FixedTypedArray<Traits>::from_double(
4121 double value) {
4122 return static_cast<ElementType>(DoubleToInt32(value));
4123 }
4124
4125
4126 template<> inline
from_double(double value)4127 uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from_double(double value) {
4128 if (value < 0) return 0;
4129 if (value > 0xFF) return 0xFF;
4130 return static_cast<uint8_t>(lrint(value));
4131 }
4132
4133
4134 template<> inline
from_double(double value)4135 float FixedTypedArray<Float32ArrayTraits>::from_double(double value) {
4136 return static_cast<float>(value);
4137 }
4138
4139
4140 template<> inline
from_double(double value)4141 double FixedTypedArray<Float64ArrayTraits>::from_double(double value) {
4142 return value;
4143 }
4144
4145
4146 template <class Traits>
get(Handle<FixedTypedArray<Traits>> array,int index)4147 Handle<Object> FixedTypedArray<Traits>::get(
4148 Handle<FixedTypedArray<Traits> > array,
4149 int index) {
4150 return Traits::ToHandle(array->GetIsolate(), array->get_scalar(index));
4151 }
4152
4153
4154 template <class Traits>
SetValue(Handle<FixedTypedArray<Traits>> array,uint32_t index,Handle<Object> value)4155 Handle<Object> FixedTypedArray<Traits>::SetValue(
4156 Handle<FixedTypedArray<Traits> > array,
4157 uint32_t index,
4158 Handle<Object> value) {
4159 ElementType cast_value = Traits::defaultValue();
4160 if (index < static_cast<uint32_t>(array->length())) {
4161 if (value->IsSmi()) {
4162 int int_value = Handle<Smi>::cast(value)->value();
4163 cast_value = from_int(int_value);
4164 } else if (value->IsHeapNumber()) {
4165 double double_value = Handle<HeapNumber>::cast(value)->value();
4166 cast_value = from_double(double_value);
4167 } else {
4168 // Clamp undefined to the default value. All other types have been
4169 // converted to a number type further up in the call chain.
4170 DCHECK(value->IsUndefined());
4171 }
4172 array->set(index, cast_value);
4173 }
4174 return Traits::ToHandle(array->GetIsolate(), cast_value);
4175 }
4176
4177
ToHandle(Isolate * isolate,uint8_t scalar)4178 Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) {
4179 return handle(Smi::FromInt(scalar), isolate);
4180 }
4181
4182
ToHandle(Isolate * isolate,uint8_t scalar)4183 Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate,
4184 uint8_t scalar) {
4185 return handle(Smi::FromInt(scalar), isolate);
4186 }
4187
4188
ToHandle(Isolate * isolate,int8_t scalar)4189 Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) {
4190 return handle(Smi::FromInt(scalar), isolate);
4191 }
4192
4193
ToHandle(Isolate * isolate,uint16_t scalar)4194 Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) {
4195 return handle(Smi::FromInt(scalar), isolate);
4196 }
4197
4198
ToHandle(Isolate * isolate,int16_t scalar)4199 Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) {
4200 return handle(Smi::FromInt(scalar), isolate);
4201 }
4202
4203
ToHandle(Isolate * isolate,uint32_t scalar)4204 Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) {
4205 return isolate->factory()->NewNumberFromUint(scalar);
4206 }
4207
4208
ToHandle(Isolate * isolate,int32_t scalar)4209 Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) {
4210 return isolate->factory()->NewNumberFromInt(scalar);
4211 }
4212
4213
ToHandle(Isolate * isolate,float scalar)4214 Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) {
4215 return isolate->factory()->NewNumber(scalar);
4216 }
4217
4218
ToHandle(Isolate * isolate,double scalar)4219 Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
4220 return isolate->factory()->NewNumber(scalar);
4221 }
4222
4223
visitor_id()4224 int Map::visitor_id() {
4225 return READ_BYTE_FIELD(this, kVisitorIdOffset);
4226 }
4227
4228
set_visitor_id(int id)4229 void Map::set_visitor_id(int id) {
4230 DCHECK(0 <= id && id < 256);
4231 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
4232 }
4233
4234
instance_size()4235 int Map::instance_size() {
4236 return NOBARRIER_READ_BYTE_FIELD(
4237 this, kInstanceSizeOffset) << kPointerSizeLog2;
4238 }
4239
4240
inobject_properties()4241 int Map::inobject_properties() {
4242 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
4243 }
4244
4245
pre_allocated_property_fields()4246 int Map::pre_allocated_property_fields() {
4247 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
4248 }
4249
4250
GetInObjectPropertyOffset(int index)4251 int Map::GetInObjectPropertyOffset(int index) {
4252 // Adjust for the number of properties stored in the object.
4253 index -= inobject_properties();
4254 DCHECK(index <= 0);
4255 return instance_size() + (index * kPointerSize);
4256 }
4257
4258
SizeFromMap(Map * map)4259 int HeapObject::SizeFromMap(Map* map) {
4260 int instance_size = map->instance_size();
4261 if (instance_size != kVariableSizeSentinel) return instance_size;
4262 // Only inline the most frequent cases.
4263 InstanceType instance_type = map->instance_type();
4264 if (instance_type == FIXED_ARRAY_TYPE) {
4265 return FixedArray::BodyDescriptor::SizeOf(map, this);
4266 }
4267 if (instance_type == ONE_BYTE_STRING_TYPE ||
4268 instance_type == ONE_BYTE_INTERNALIZED_STRING_TYPE) {
4269 return SeqOneByteString::SizeFor(
4270 reinterpret_cast<SeqOneByteString*>(this)->length());
4271 }
4272 if (instance_type == BYTE_ARRAY_TYPE) {
4273 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
4274 }
4275 if (instance_type == FREE_SPACE_TYPE) {
4276 return reinterpret_cast<FreeSpace*>(this)->nobarrier_size();
4277 }
4278 if (instance_type == STRING_TYPE ||
4279 instance_type == INTERNALIZED_STRING_TYPE) {
4280 return SeqTwoByteString::SizeFor(
4281 reinterpret_cast<SeqTwoByteString*>(this)->length());
4282 }
4283 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
4284 return FixedDoubleArray::SizeFor(
4285 reinterpret_cast<FixedDoubleArray*>(this)->length());
4286 }
4287 if (instance_type == CONSTANT_POOL_ARRAY_TYPE) {
4288 return reinterpret_cast<ConstantPoolArray*>(this)->size();
4289 }
4290 if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
4291 instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) {
4292 return reinterpret_cast<FixedTypedArrayBase*>(
4293 this)->TypedArraySize(instance_type);
4294 }
4295 DCHECK(instance_type == CODE_TYPE);
4296 return reinterpret_cast<Code*>(this)->CodeSize();
4297 }
4298
4299
set_instance_size(int value)4300 void Map::set_instance_size(int value) {
4301 DCHECK_EQ(0, value & (kPointerSize - 1));
4302 value >>= kPointerSizeLog2;
4303 DCHECK(0 <= value && value < 256);
4304 NOBARRIER_WRITE_BYTE_FIELD(
4305 this, kInstanceSizeOffset, static_cast<byte>(value));
4306 }
4307
4308
set_inobject_properties(int value)4309 void Map::set_inobject_properties(int value) {
4310 DCHECK(0 <= value && value < 256);
4311 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
4312 }
4313
4314
set_pre_allocated_property_fields(int value)4315 void Map::set_pre_allocated_property_fields(int value) {
4316 DCHECK(0 <= value && value < 256);
4317 WRITE_BYTE_FIELD(this,
4318 kPreAllocatedPropertyFieldsOffset,
4319 static_cast<byte>(value));
4320 }
4321
4322
instance_type()4323 InstanceType Map::instance_type() {
4324 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
4325 }
4326
4327
set_instance_type(InstanceType value)4328 void Map::set_instance_type(InstanceType value) {
4329 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
4330 }
4331
4332
unused_property_fields()4333 int Map::unused_property_fields() {
4334 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
4335 }
4336
4337
set_unused_property_fields(int value)4338 void Map::set_unused_property_fields(int value) {
4339 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
4340 }
4341
4342
bit_field()4343 byte Map::bit_field() {
4344 return READ_BYTE_FIELD(this, kBitFieldOffset);
4345 }
4346
4347
set_bit_field(byte value)4348 void Map::set_bit_field(byte value) {
4349 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
4350 }
4351
4352
bit_field2()4353 byte Map::bit_field2() {
4354 return READ_BYTE_FIELD(this, kBitField2Offset);
4355 }
4356
4357
set_bit_field2(byte value)4358 void Map::set_bit_field2(byte value) {
4359 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
4360 }
4361
4362
set_non_instance_prototype(bool value)4363 void Map::set_non_instance_prototype(bool value) {
4364 if (value) {
4365 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
4366 } else {
4367 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
4368 }
4369 }
4370
4371
has_non_instance_prototype()4372 bool Map::has_non_instance_prototype() {
4373 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
4374 }
4375
4376
set_function_with_prototype(bool value)4377 void Map::set_function_with_prototype(bool value) {
4378 set_bit_field(FunctionWithPrototype::update(bit_field(), value));
4379 }
4380
4381
function_with_prototype()4382 bool Map::function_with_prototype() {
4383 return FunctionWithPrototype::decode(bit_field());
4384 }
4385
4386
set_is_access_check_needed(bool access_check_needed)4387 void Map::set_is_access_check_needed(bool access_check_needed) {
4388 if (access_check_needed) {
4389 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
4390 } else {
4391 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
4392 }
4393 }
4394
4395
is_access_check_needed()4396 bool Map::is_access_check_needed() {
4397 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
4398 }
4399
4400
set_is_extensible(bool value)4401 void Map::set_is_extensible(bool value) {
4402 if (value) {
4403 set_bit_field2(bit_field2() | (1 << kIsExtensible));
4404 } else {
4405 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
4406 }
4407 }
4408
is_extensible()4409 bool Map::is_extensible() {
4410 return ((1 << kIsExtensible) & bit_field2()) != 0;
4411 }
4412
4413
set_is_prototype_map(bool value)4414 void Map::set_is_prototype_map(bool value) {
4415 set_bit_field2(IsPrototypeMapBits::update(bit_field2(), value));
4416 }
4417
is_prototype_map()4418 bool Map::is_prototype_map() {
4419 return IsPrototypeMapBits::decode(bit_field2());
4420 }
4421
4422
set_dictionary_map(bool value)4423 void Map::set_dictionary_map(bool value) {
4424 uint32_t new_bit_field3 = DictionaryMap::update(bit_field3(), value);
4425 new_bit_field3 = IsUnstable::update(new_bit_field3, value);
4426 set_bit_field3(new_bit_field3);
4427 }
4428
4429
is_dictionary_map()4430 bool Map::is_dictionary_map() {
4431 return DictionaryMap::decode(bit_field3());
4432 }
4433
4434
flags()4435 Code::Flags Code::flags() {
4436 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
4437 }
4438
4439
set_owns_descriptors(bool owns_descriptors)4440 void Map::set_owns_descriptors(bool owns_descriptors) {
4441 set_bit_field3(OwnsDescriptors::update(bit_field3(), owns_descriptors));
4442 }
4443
4444
owns_descriptors()4445 bool Map::owns_descriptors() {
4446 return OwnsDescriptors::decode(bit_field3());
4447 }
4448
4449
set_has_instance_call_handler()4450 void Map::set_has_instance_call_handler() {
4451 set_bit_field3(HasInstanceCallHandler::update(bit_field3(), true));
4452 }
4453
4454
has_instance_call_handler()4455 bool Map::has_instance_call_handler() {
4456 return HasInstanceCallHandler::decode(bit_field3());
4457 }
4458
4459
deprecate()4460 void Map::deprecate() {
4461 set_bit_field3(Deprecated::update(bit_field3(), true));
4462 }
4463
4464
is_deprecated()4465 bool Map::is_deprecated() {
4466 return Deprecated::decode(bit_field3());
4467 }
4468
4469
set_migration_target(bool value)4470 void Map::set_migration_target(bool value) {
4471 set_bit_field3(IsMigrationTarget::update(bit_field3(), value));
4472 }
4473
4474
is_migration_target()4475 bool Map::is_migration_target() {
4476 return IsMigrationTarget::decode(bit_field3());
4477 }
4478
4479
set_done_inobject_slack_tracking(bool value)4480 void Map::set_done_inobject_slack_tracking(bool value) {
4481 set_bit_field3(DoneInobjectSlackTracking::update(bit_field3(), value));
4482 }
4483
4484
done_inobject_slack_tracking()4485 bool Map::done_inobject_slack_tracking() {
4486 return DoneInobjectSlackTracking::decode(bit_field3());
4487 }
4488
4489
set_construction_count(int value)4490 void Map::set_construction_count(int value) {
4491 set_bit_field3(ConstructionCount::update(bit_field3(), value));
4492 }
4493
4494
construction_count()4495 int Map::construction_count() {
4496 return ConstructionCount::decode(bit_field3());
4497 }
4498
4499
freeze()4500 void Map::freeze() {
4501 set_bit_field3(IsFrozen::update(bit_field3(), true));
4502 }
4503
4504
is_frozen()4505 bool Map::is_frozen() {
4506 return IsFrozen::decode(bit_field3());
4507 }
4508
4509
mark_unstable()4510 void Map::mark_unstable() {
4511 set_bit_field3(IsUnstable::update(bit_field3(), true));
4512 }
4513
4514
is_stable()4515 bool Map::is_stable() {
4516 return !IsUnstable::decode(bit_field3());
4517 }
4518
4519
has_code_cache()4520 bool Map::has_code_cache() {
4521 return code_cache() != GetIsolate()->heap()->empty_fixed_array();
4522 }
4523
4524
CanBeDeprecated()4525 bool Map::CanBeDeprecated() {
4526 int descriptor = LastAdded();
4527 for (int i = 0; i <= descriptor; i++) {
4528 PropertyDetails details = instance_descriptors()->GetDetails(i);
4529 if (details.representation().IsNone()) return true;
4530 if (details.representation().IsSmi()) return true;
4531 if (details.representation().IsDouble()) return true;
4532 if (details.representation().IsHeapObject()) return true;
4533 if (details.type() == CONSTANT) return true;
4534 }
4535 return false;
4536 }
4537
4538
NotifyLeafMapLayoutChange()4539 void Map::NotifyLeafMapLayoutChange() {
4540 if (is_stable()) {
4541 mark_unstable();
4542 dependent_code()->DeoptimizeDependentCodeGroup(
4543 GetIsolate(),
4544 DependentCode::kPrototypeCheckGroup);
4545 }
4546 }
4547
4548
CanOmitMapChecks()4549 bool Map::CanOmitMapChecks() {
4550 return is_stable() && FLAG_omit_map_checks_for_leaf_maps;
4551 }
4552
4553
number_of_entries(DependencyGroup group)4554 int DependentCode::number_of_entries(DependencyGroup group) {
4555 if (length() == 0) return 0;
4556 return Smi::cast(get(group))->value();
4557 }
4558
4559
set_number_of_entries(DependencyGroup group,int value)4560 void DependentCode::set_number_of_entries(DependencyGroup group, int value) {
4561 set(group, Smi::FromInt(value));
4562 }
4563
4564
is_code_at(int i)4565 bool DependentCode::is_code_at(int i) {
4566 return get(kCodesStartIndex + i)->IsCode();
4567 }
4568
code_at(int i)4569 Code* DependentCode::code_at(int i) {
4570 return Code::cast(get(kCodesStartIndex + i));
4571 }
4572
4573
compilation_info_at(int i)4574 CompilationInfo* DependentCode::compilation_info_at(int i) {
4575 return reinterpret_cast<CompilationInfo*>(
4576 Foreign::cast(get(kCodesStartIndex + i))->foreign_address());
4577 }
4578
4579
set_object_at(int i,Object * object)4580 void DependentCode::set_object_at(int i, Object* object) {
4581 set(kCodesStartIndex + i, object);
4582 }
4583
4584
object_at(int i)4585 Object* DependentCode::object_at(int i) {
4586 return get(kCodesStartIndex + i);
4587 }
4588
4589
slot_at(int i)4590 Object** DependentCode::slot_at(int i) {
4591 return RawFieldOfElementAt(kCodesStartIndex + i);
4592 }
4593
4594
clear_at(int i)4595 void DependentCode::clear_at(int i) {
4596 set_undefined(kCodesStartIndex + i);
4597 }
4598
4599
copy(int from,int to)4600 void DependentCode::copy(int from, int to) {
4601 set(kCodesStartIndex + to, get(kCodesStartIndex + from));
4602 }
4603
4604
ExtendGroup(DependencyGroup group)4605 void DependentCode::ExtendGroup(DependencyGroup group) {
4606 GroupStartIndexes starts(this);
4607 for (int g = kGroupCount - 1; g > group; g--) {
4608 if (starts.at(g) < starts.at(g + 1)) {
4609 copy(starts.at(g), starts.at(g + 1));
4610 }
4611 }
4612 }
4613
4614
set_flags(Code::Flags flags)4615 void Code::set_flags(Code::Flags flags) {
4616 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
4617 WRITE_INT_FIELD(this, kFlagsOffset, flags);
4618 }
4619
4620
kind()4621 Code::Kind Code::kind() {
4622 return ExtractKindFromFlags(flags());
4623 }
4624
4625
IsCodeStubOrIC()4626 bool Code::IsCodeStubOrIC() {
4627 return kind() == STUB || kind() == HANDLER || kind() == LOAD_IC ||
4628 kind() == KEYED_LOAD_IC || kind() == CALL_IC || kind() == STORE_IC ||
4629 kind() == KEYED_STORE_IC || kind() == BINARY_OP_IC ||
4630 kind() == COMPARE_IC || kind() == COMPARE_NIL_IC ||
4631 kind() == TO_BOOLEAN_IC;
4632 }
4633
4634
ic_state()4635 InlineCacheState Code::ic_state() {
4636 InlineCacheState result = ExtractICStateFromFlags(flags());
4637 // Only allow uninitialized or debugger states for non-IC code
4638 // objects. This is used in the debugger to determine whether or not
4639 // a call to code object has been replaced with a debug break call.
4640 DCHECK(is_inline_cache_stub() ||
4641 result == UNINITIALIZED ||
4642 result == DEBUG_STUB);
4643 return result;
4644 }
4645
4646
extra_ic_state()4647 ExtraICState Code::extra_ic_state() {
4648 DCHECK(is_inline_cache_stub() || ic_state() == DEBUG_STUB);
4649 return ExtractExtraICStateFromFlags(flags());
4650 }
4651
4652
type()4653 Code::StubType Code::type() {
4654 return ExtractTypeFromFlags(flags());
4655 }
4656
4657
4658 // For initialization.
set_raw_kind_specific_flags1(int value)4659 void Code::set_raw_kind_specific_flags1(int value) {
4660 WRITE_INT_FIELD(this, kKindSpecificFlags1Offset, value);
4661 }
4662
4663
set_raw_kind_specific_flags2(int value)4664 void Code::set_raw_kind_specific_flags2(int value) {
4665 WRITE_INT_FIELD(this, kKindSpecificFlags2Offset, value);
4666 }
4667
4668
is_crankshafted()4669 inline bool Code::is_crankshafted() {
4670 return IsCrankshaftedField::decode(
4671 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
4672 }
4673
4674
is_hydrogen_stub()4675 inline bool Code::is_hydrogen_stub() {
4676 return is_crankshafted() && kind() != OPTIMIZED_FUNCTION;
4677 }
4678
4679
set_is_crankshafted(bool value)4680 inline void Code::set_is_crankshafted(bool value) {
4681 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4682 int updated = IsCrankshaftedField::update(previous, value);
4683 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4684 }
4685
4686
is_turbofanned()4687 inline bool Code::is_turbofanned() {
4688 DCHECK(kind() == OPTIMIZED_FUNCTION || kind() == STUB);
4689 return IsTurbofannedField::decode(
4690 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4691 }
4692
4693
set_is_turbofanned(bool value)4694 inline void Code::set_is_turbofanned(bool value) {
4695 DCHECK(kind() == OPTIMIZED_FUNCTION || kind() == STUB);
4696 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4697 int updated = IsTurbofannedField::update(previous, value);
4698 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4699 }
4700
4701
optimizable()4702 bool Code::optimizable() {
4703 DCHECK_EQ(FUNCTION, kind());
4704 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
4705 }
4706
4707
set_optimizable(bool value)4708 void Code::set_optimizable(bool value) {
4709 DCHECK_EQ(FUNCTION, kind());
4710 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
4711 }
4712
4713
has_deoptimization_support()4714 bool Code::has_deoptimization_support() {
4715 DCHECK_EQ(FUNCTION, kind());
4716 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4717 return FullCodeFlagsHasDeoptimizationSupportField::decode(flags);
4718 }
4719
4720
set_has_deoptimization_support(bool value)4721 void Code::set_has_deoptimization_support(bool value) {
4722 DCHECK_EQ(FUNCTION, kind());
4723 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4724 flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value);
4725 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4726 }
4727
4728
has_debug_break_slots()4729 bool Code::has_debug_break_slots() {
4730 DCHECK_EQ(FUNCTION, kind());
4731 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4732 return FullCodeFlagsHasDebugBreakSlotsField::decode(flags);
4733 }
4734
4735
set_has_debug_break_slots(bool value)4736 void Code::set_has_debug_break_slots(bool value) {
4737 DCHECK_EQ(FUNCTION, kind());
4738 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4739 flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value);
4740 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4741 }
4742
4743
is_compiled_optimizable()4744 bool Code::is_compiled_optimizable() {
4745 DCHECK_EQ(FUNCTION, kind());
4746 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4747 return FullCodeFlagsIsCompiledOptimizable::decode(flags);
4748 }
4749
4750
set_compiled_optimizable(bool value)4751 void Code::set_compiled_optimizable(bool value) {
4752 DCHECK_EQ(FUNCTION, kind());
4753 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4754 flags = FullCodeFlagsIsCompiledOptimizable::update(flags, value);
4755 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4756 }
4757
4758
allow_osr_at_loop_nesting_level()4759 int Code::allow_osr_at_loop_nesting_level() {
4760 DCHECK_EQ(FUNCTION, kind());
4761 int fields = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4762 return AllowOSRAtLoopNestingLevelField::decode(fields);
4763 }
4764
4765
set_allow_osr_at_loop_nesting_level(int level)4766 void Code::set_allow_osr_at_loop_nesting_level(int level) {
4767 DCHECK_EQ(FUNCTION, kind());
4768 DCHECK(level >= 0 && level <= kMaxLoopNestingMarker);
4769 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4770 int updated = AllowOSRAtLoopNestingLevelField::update(previous, level);
4771 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4772 }
4773
4774
profiler_ticks()4775 int Code::profiler_ticks() {
4776 DCHECK_EQ(FUNCTION, kind());
4777 return READ_BYTE_FIELD(this, kProfilerTicksOffset);
4778 }
4779
4780
set_profiler_ticks(int ticks)4781 void Code::set_profiler_ticks(int ticks) {
4782 DCHECK(ticks < 256);
4783 if (kind() == FUNCTION) {
4784 WRITE_BYTE_FIELD(this, kProfilerTicksOffset, ticks);
4785 }
4786 }
4787
4788
builtin_index()4789 int Code::builtin_index() {
4790 DCHECK_EQ(BUILTIN, kind());
4791 return READ_INT32_FIELD(this, kKindSpecificFlags1Offset);
4792 }
4793
4794
set_builtin_index(int index)4795 void Code::set_builtin_index(int index) {
4796 DCHECK_EQ(BUILTIN, kind());
4797 WRITE_INT32_FIELD(this, kKindSpecificFlags1Offset, index);
4798 }
4799
4800
stack_slots()4801 unsigned Code::stack_slots() {
4802 DCHECK(is_crankshafted());
4803 return StackSlotsField::decode(
4804 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4805 }
4806
4807
set_stack_slots(unsigned slots)4808 void Code::set_stack_slots(unsigned slots) {
4809 CHECK(slots <= (1 << kStackSlotsBitCount));
4810 DCHECK(is_crankshafted());
4811 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4812 int updated = StackSlotsField::update(previous, slots);
4813 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4814 }
4815
4816
safepoint_table_offset()4817 unsigned Code::safepoint_table_offset() {
4818 DCHECK(is_crankshafted());
4819 return SafepointTableOffsetField::decode(
4820 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
4821 }
4822
4823
set_safepoint_table_offset(unsigned offset)4824 void Code::set_safepoint_table_offset(unsigned offset) {
4825 CHECK(offset <= (1 << kSafepointTableOffsetBitCount));
4826 DCHECK(is_crankshafted());
4827 DCHECK(IsAligned(offset, static_cast<unsigned>(kIntSize)));
4828 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4829 int updated = SafepointTableOffsetField::update(previous, offset);
4830 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4831 }
4832
4833
back_edge_table_offset()4834 unsigned Code::back_edge_table_offset() {
4835 DCHECK_EQ(FUNCTION, kind());
4836 return BackEdgeTableOffsetField::decode(
4837 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset)) << kPointerSizeLog2;
4838 }
4839
4840
set_back_edge_table_offset(unsigned offset)4841 void Code::set_back_edge_table_offset(unsigned offset) {
4842 DCHECK_EQ(FUNCTION, kind());
4843 DCHECK(IsAligned(offset, static_cast<unsigned>(kPointerSize)));
4844 offset = offset >> kPointerSizeLog2;
4845 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4846 int updated = BackEdgeTableOffsetField::update(previous, offset);
4847 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4848 }
4849
4850
back_edges_patched_for_osr()4851 bool Code::back_edges_patched_for_osr() {
4852 DCHECK_EQ(FUNCTION, kind());
4853 return allow_osr_at_loop_nesting_level() > 0;
4854 }
4855
4856
to_boolean_state()4857 byte Code::to_boolean_state() {
4858 return extra_ic_state();
4859 }
4860
4861
has_function_cache()4862 bool Code::has_function_cache() {
4863 DCHECK(kind() == STUB);
4864 return HasFunctionCacheField::decode(
4865 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4866 }
4867
4868
set_has_function_cache(bool flag)4869 void Code::set_has_function_cache(bool flag) {
4870 DCHECK(kind() == STUB);
4871 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4872 int updated = HasFunctionCacheField::update(previous, flag);
4873 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4874 }
4875
4876
marked_for_deoptimization()4877 bool Code::marked_for_deoptimization() {
4878 DCHECK(kind() == OPTIMIZED_FUNCTION);
4879 return MarkedForDeoptimizationField::decode(
4880 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4881 }
4882
4883
set_marked_for_deoptimization(bool flag)4884 void Code::set_marked_for_deoptimization(bool flag) {
4885 DCHECK(kind() == OPTIMIZED_FUNCTION);
4886 DCHECK(!flag || AllowDeoptimization::IsAllowed(GetIsolate()));
4887 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4888 int updated = MarkedForDeoptimizationField::update(previous, flag);
4889 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4890 }
4891
4892
is_weak_stub()4893 bool Code::is_weak_stub() {
4894 return CanBeWeakStub() && WeakStubField::decode(
4895 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4896 }
4897
4898
mark_as_weak_stub()4899 void Code::mark_as_weak_stub() {
4900 DCHECK(CanBeWeakStub());
4901 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4902 int updated = WeakStubField::update(previous, true);
4903 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4904 }
4905
4906
is_invalidated_weak_stub()4907 bool Code::is_invalidated_weak_stub() {
4908 return is_weak_stub() && InvalidatedWeakStubField::decode(
4909 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4910 }
4911
4912
mark_as_invalidated_weak_stub()4913 void Code::mark_as_invalidated_weak_stub() {
4914 DCHECK(is_inline_cache_stub());
4915 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4916 int updated = InvalidatedWeakStubField::update(previous, true);
4917 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4918 }
4919
4920
is_inline_cache_stub()4921 bool Code::is_inline_cache_stub() {
4922 Kind kind = this->kind();
4923 switch (kind) {
4924 #define CASE(name) case name: return true;
4925 IC_KIND_LIST(CASE)
4926 #undef CASE
4927 default: return false;
4928 }
4929 }
4930
4931
is_keyed_stub()4932 bool Code::is_keyed_stub() {
4933 return is_keyed_load_stub() || is_keyed_store_stub();
4934 }
4935
4936
is_debug_stub()4937 bool Code::is_debug_stub() {
4938 return ic_state() == DEBUG_STUB;
4939 }
4940
4941
constant_pool()4942 ConstantPoolArray* Code::constant_pool() {
4943 return ConstantPoolArray::cast(READ_FIELD(this, kConstantPoolOffset));
4944 }
4945
4946
set_constant_pool(Object * value)4947 void Code::set_constant_pool(Object* value) {
4948 DCHECK(value->IsConstantPoolArray());
4949 WRITE_FIELD(this, kConstantPoolOffset, value);
4950 WRITE_BARRIER(GetHeap(), this, kConstantPoolOffset, value);
4951 }
4952
4953
ComputeFlags(Kind kind,InlineCacheState ic_state,ExtraICState extra_ic_state,StubType type,CacheHolderFlag holder)4954 Code::Flags Code::ComputeFlags(Kind kind, InlineCacheState ic_state,
4955 ExtraICState extra_ic_state, StubType type,
4956 CacheHolderFlag holder) {
4957 // Compute the bit mask.
4958 unsigned int bits = KindField::encode(kind)
4959 | ICStateField::encode(ic_state)
4960 | TypeField::encode(type)
4961 | ExtraICStateField::encode(extra_ic_state)
4962 | CacheHolderField::encode(holder);
4963 return static_cast<Flags>(bits);
4964 }
4965
4966
ComputeMonomorphicFlags(Kind kind,ExtraICState extra_ic_state,CacheHolderFlag holder,StubType type)4967 Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
4968 ExtraICState extra_ic_state,
4969 CacheHolderFlag holder,
4970 StubType type) {
4971 return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, holder);
4972 }
4973
4974
ComputeHandlerFlags(Kind handler_kind,StubType type,CacheHolderFlag holder)4975 Code::Flags Code::ComputeHandlerFlags(Kind handler_kind, StubType type,
4976 CacheHolderFlag holder) {
4977 return ComputeFlags(Code::HANDLER, MONOMORPHIC, handler_kind, type, holder);
4978 }
4979
4980
ExtractKindFromFlags(Flags flags)4981 Code::Kind Code::ExtractKindFromFlags(Flags flags) {
4982 return KindField::decode(flags);
4983 }
4984
4985
ExtractICStateFromFlags(Flags flags)4986 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
4987 return ICStateField::decode(flags);
4988 }
4989
4990
ExtractExtraICStateFromFlags(Flags flags)4991 ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
4992 return ExtraICStateField::decode(flags);
4993 }
4994
4995
ExtractTypeFromFlags(Flags flags)4996 Code::StubType Code::ExtractTypeFromFlags(Flags flags) {
4997 return TypeField::decode(flags);
4998 }
4999
5000
ExtractCacheHolderFromFlags(Flags flags)5001 CacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
5002 return CacheHolderField::decode(flags);
5003 }
5004
5005
RemoveTypeFromFlags(Flags flags)5006 Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
5007 int bits = flags & ~TypeField::kMask;
5008 return static_cast<Flags>(bits);
5009 }
5010
5011
RemoveTypeAndHolderFromFlags(Flags flags)5012 Code::Flags Code::RemoveTypeAndHolderFromFlags(Flags flags) {
5013 int bits = flags & ~TypeField::kMask & ~CacheHolderField::kMask;
5014 return static_cast<Flags>(bits);
5015 }
5016
5017
GetCodeFromTargetAddress(Address address)5018 Code* Code::GetCodeFromTargetAddress(Address address) {
5019 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
5020 // GetCodeFromTargetAddress might be called when marking objects during mark
5021 // sweep. reinterpret_cast is therefore used instead of the more appropriate
5022 // Code::cast. Code::cast does not work when the object's map is
5023 // marked.
5024 Code* result = reinterpret_cast<Code*>(code);
5025 return result;
5026 }
5027
5028
GetObjectFromEntryAddress(Address location_of_address)5029 Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
5030 return HeapObject::
5031 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
5032 }
5033
5034
IsWeakObjectInOptimizedCode(Object * object)5035 bool Code::IsWeakObjectInOptimizedCode(Object* object) {
5036 if (!FLAG_collect_maps) return false;
5037 if (object->IsMap()) {
5038 return Map::cast(object)->CanTransition() &&
5039 FLAG_weak_embedded_maps_in_optimized_code;
5040 }
5041 if (object->IsJSObject() ||
5042 (object->IsCell() && Cell::cast(object)->value()->IsJSObject())) {
5043 return FLAG_weak_embedded_objects_in_optimized_code;
5044 }
5045 return false;
5046 }
5047
5048
5049 class Code::FindAndReplacePattern {
5050 public:
FindAndReplacePattern()5051 FindAndReplacePattern() : count_(0) { }
Add(Handle<Map> map_to_find,Handle<Object> obj_to_replace)5052 void Add(Handle<Map> map_to_find, Handle<Object> obj_to_replace) {
5053 DCHECK(count_ < kMaxCount);
5054 find_[count_] = map_to_find;
5055 replace_[count_] = obj_to_replace;
5056 ++count_;
5057 }
5058 private:
5059 static const int kMaxCount = 4;
5060 int count_;
5061 Handle<Map> find_[kMaxCount];
5062 Handle<Object> replace_[kMaxCount];
5063 friend class Code;
5064 };
5065
5066
IsWeakObjectInIC(Object * object)5067 bool Code::IsWeakObjectInIC(Object* object) {
5068 return object->IsMap() && Map::cast(object)->CanTransition() &&
5069 FLAG_collect_maps &&
5070 FLAG_weak_embedded_maps_in_ic;
5071 }
5072
5073
prototype()5074 Object* Map::prototype() const {
5075 return READ_FIELD(this, kPrototypeOffset);
5076 }
5077
5078
set_prototype(Object * value,WriteBarrierMode mode)5079 void Map::set_prototype(Object* value, WriteBarrierMode mode) {
5080 DCHECK(value->IsNull() || value->IsJSReceiver());
5081 WRITE_FIELD(this, kPrototypeOffset, value);
5082 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode);
5083 }
5084
5085
5086 // If the descriptor is using the empty transition array, install a new empty
5087 // transition array that will have place for an element transition.
EnsureHasTransitionArray(Handle<Map> map)5088 static void EnsureHasTransitionArray(Handle<Map> map) {
5089 Handle<TransitionArray> transitions;
5090 if (!map->HasTransitionArray()) {
5091 transitions = TransitionArray::Allocate(map->GetIsolate(), 0);
5092 transitions->set_back_pointer_storage(map->GetBackPointer());
5093 } else if (!map->transitions()->IsFullTransitionArray()) {
5094 transitions = TransitionArray::ExtendToFullTransitionArray(map);
5095 } else {
5096 return;
5097 }
5098 map->set_transitions(*transitions);
5099 }
5100
5101
InitializeDescriptors(DescriptorArray * descriptors)5102 void Map::InitializeDescriptors(DescriptorArray* descriptors) {
5103 int len = descriptors->number_of_descriptors();
5104 set_instance_descriptors(descriptors);
5105 SetNumberOfOwnDescriptors(len);
5106 }
5107
5108
ACCESSORS(Map,instance_descriptors,DescriptorArray,kDescriptorsOffset)5109 ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset)
5110
5111
5112 void Map::set_bit_field3(uint32_t bits) {
5113 if (kInt32Size != kPointerSize) {
5114 WRITE_UINT32_FIELD(this, kBitField3Offset + kInt32Size, 0);
5115 }
5116 WRITE_UINT32_FIELD(this, kBitField3Offset, bits);
5117 }
5118
5119
bit_field3()5120 uint32_t Map::bit_field3() {
5121 return READ_UINT32_FIELD(this, kBitField3Offset);
5122 }
5123
5124
AppendDescriptor(Descriptor * desc)5125 void Map::AppendDescriptor(Descriptor* desc) {
5126 DescriptorArray* descriptors = instance_descriptors();
5127 int number_of_own_descriptors = NumberOfOwnDescriptors();
5128 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors);
5129 descriptors->Append(desc);
5130 SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
5131 }
5132
5133
GetBackPointer()5134 Object* Map::GetBackPointer() {
5135 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
5136 if (object->IsDescriptorArray()) {
5137 return TransitionArray::cast(object)->back_pointer_storage();
5138 } else {
5139 DCHECK(object->IsMap() || object->IsUndefined());
5140 return object;
5141 }
5142 }
5143
5144
HasElementsTransition()5145 bool Map::HasElementsTransition() {
5146 return HasTransitionArray() && transitions()->HasElementsTransition();
5147 }
5148
5149
HasTransitionArray()5150 bool Map::HasTransitionArray() const {
5151 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
5152 return object->IsTransitionArray();
5153 }
5154
5155
elements_transition_map()5156 Map* Map::elements_transition_map() {
5157 int index = transitions()->Search(GetHeap()->elements_transition_symbol());
5158 return transitions()->GetTarget(index);
5159 }
5160
5161
CanHaveMoreTransitions()5162 bool Map::CanHaveMoreTransitions() {
5163 if (!HasTransitionArray()) return true;
5164 return FixedArray::SizeFor(transitions()->length() +
5165 TransitionArray::kTransitionSize)
5166 <= Page::kMaxRegularHeapObjectSize;
5167 }
5168
5169
GetTransition(int transition_index)5170 Map* Map::GetTransition(int transition_index) {
5171 return transitions()->GetTarget(transition_index);
5172 }
5173
5174
SearchTransition(Name * name)5175 int Map::SearchTransition(Name* name) {
5176 if (HasTransitionArray()) return transitions()->Search(name);
5177 return TransitionArray::kNotFound;
5178 }
5179
5180
GetPrototypeTransitions()5181 FixedArray* Map::GetPrototypeTransitions() {
5182 if (!HasTransitionArray()) return GetHeap()->empty_fixed_array();
5183 if (!transitions()->HasPrototypeTransitions()) {
5184 return GetHeap()->empty_fixed_array();
5185 }
5186 return transitions()->GetPrototypeTransitions();
5187 }
5188
5189
SetPrototypeTransitions(Handle<Map> map,Handle<FixedArray> proto_transitions)5190 void Map::SetPrototypeTransitions(
5191 Handle<Map> map, Handle<FixedArray> proto_transitions) {
5192 EnsureHasTransitionArray(map);
5193 int old_number_of_transitions = map->NumberOfProtoTransitions();
5194 #ifdef DEBUG
5195 if (map->HasPrototypeTransitions()) {
5196 DCHECK(map->GetPrototypeTransitions() != *proto_transitions);
5197 map->ZapPrototypeTransitions();
5198 }
5199 #endif
5200 map->transitions()->SetPrototypeTransitions(*proto_transitions);
5201 map->SetNumberOfProtoTransitions(old_number_of_transitions);
5202 }
5203
5204
HasPrototypeTransitions()5205 bool Map::HasPrototypeTransitions() {
5206 return HasTransitionArray() && transitions()->HasPrototypeTransitions();
5207 }
5208
5209
transitions()5210 TransitionArray* Map::transitions() const {
5211 DCHECK(HasTransitionArray());
5212 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
5213 return TransitionArray::cast(object);
5214 }
5215
5216
set_transitions(TransitionArray * transition_array,WriteBarrierMode mode)5217 void Map::set_transitions(TransitionArray* transition_array,
5218 WriteBarrierMode mode) {
5219 // Transition arrays are not shared. When one is replaced, it should not
5220 // keep referenced objects alive, so we zap it.
5221 // When there is another reference to the array somewhere (e.g. a handle),
5222 // not zapping turns from a waste of memory into a source of crashes.
5223 if (HasTransitionArray()) {
5224 #ifdef DEBUG
5225 for (int i = 0; i < transitions()->number_of_transitions(); i++) {
5226 Map* target = transitions()->GetTarget(i);
5227 if (target->instance_descriptors() == instance_descriptors()) {
5228 Name* key = transitions()->GetKey(i);
5229 int new_target_index = transition_array->Search(key);
5230 DCHECK(new_target_index != TransitionArray::kNotFound);
5231 DCHECK(transition_array->GetTarget(new_target_index) == target);
5232 }
5233 }
5234 #endif
5235 DCHECK(transitions() != transition_array);
5236 ZapTransitions();
5237 }
5238
5239 WRITE_FIELD(this, kTransitionsOrBackPointerOffset, transition_array);
5240 CONDITIONAL_WRITE_BARRIER(
5241 GetHeap(), this, kTransitionsOrBackPointerOffset, transition_array, mode);
5242 }
5243
5244
init_back_pointer(Object * undefined)5245 void Map::init_back_pointer(Object* undefined) {
5246 DCHECK(undefined->IsUndefined());
5247 WRITE_FIELD(this, kTransitionsOrBackPointerOffset, undefined);
5248 }
5249
5250
SetBackPointer(Object * value,WriteBarrierMode mode)5251 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) {
5252 DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE);
5253 DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) ||
5254 (value->IsMap() && GetBackPointer()->IsUndefined()));
5255 Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
5256 if (object->IsTransitionArray()) {
5257 TransitionArray::cast(object)->set_back_pointer_storage(value);
5258 } else {
5259 WRITE_FIELD(this, kTransitionsOrBackPointerOffset, value);
5260 CONDITIONAL_WRITE_BARRIER(
5261 GetHeap(), this, kTransitionsOrBackPointerOffset, value, mode);
5262 }
5263 }
5264
5265
ACCESSORS(Map,code_cache,Object,kCodeCacheOffset)5266 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
5267 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset)
5268 ACCESSORS(Map, constructor, Object, kConstructorOffset)
5269
5270 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
5271 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset)
5272 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset)
5273
5274 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
5275 ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset)
5276 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
5277 ACCESSORS(GlobalObject, global_proxy, JSObject, kGlobalProxyOffset)
5278
5279 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset)
5280 ACCESSORS(JSGlobalProxy, hash, Object, kHashOffset)
5281
5282 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
5283 ACCESSORS_TO_SMI(AccessorInfo, flag, kFlagOffset)
5284 ACCESSORS(AccessorInfo, expected_receiver_type, Object,
5285 kExpectedReceiverTypeOffset)
5286
5287 ACCESSORS(DeclaredAccessorDescriptor, serialized_data, ByteArray,
5288 kSerializedDataOffset)
5289
5290 ACCESSORS(DeclaredAccessorInfo, descriptor, DeclaredAccessorDescriptor,
5291 kDescriptorOffset)
5292
5293 ACCESSORS(ExecutableAccessorInfo, getter, Object, kGetterOffset)
5294 ACCESSORS(ExecutableAccessorInfo, setter, Object, kSetterOffset)
5295 ACCESSORS(ExecutableAccessorInfo, data, Object, kDataOffset)
5296
5297 ACCESSORS(Box, value, Object, kValueOffset)
5298
5299 ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
5300 ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
5301
5302 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
5303 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
5304 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
5305
5306 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
5307 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
5308 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
5309 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
5310 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
5311 ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
5312
5313 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
5314 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
5315
5316 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
5317 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
5318 ACCESSORS(TemplateInfo, property_accessors, Object, kPropertyAccessorsOffset)
5319
5320 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
5321 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
5322 ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
5323 kPrototypeTemplateOffset)
5324 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
5325 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
5326 kNamedPropertyHandlerOffset)
5327 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
5328 kIndexedPropertyHandlerOffset)
5329 ACCESSORS(FunctionTemplateInfo, instance_template, Object,
5330 kInstanceTemplateOffset)
5331 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
5332 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
5333 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
5334 kInstanceCallHandlerOffset)
5335 ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
5336 kAccessCheckInfoOffset)
5337 ACCESSORS_TO_SMI(FunctionTemplateInfo, flag, kFlagOffset)
5338
5339 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
5340 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
5341 kInternalFieldCountOffset)
5342
5343 ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
5344 ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
5345
5346 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
5347
5348 ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset)
5349 ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
5350 ACCESSORS_TO_SMI(AllocationSite, pretenure_data, kPretenureDataOffset)
5351 ACCESSORS_TO_SMI(AllocationSite, pretenure_create_count,
5352 kPretenureCreateCountOffset)
5353 ACCESSORS(AllocationSite, dependent_code, DependentCode,
5354 kDependentCodeOffset)
5355 ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset)
5356 ACCESSORS(AllocationMemento, allocation_site, Object, kAllocationSiteOffset)
5357
5358 ACCESSORS(Script, source, Object, kSourceOffset)
5359 ACCESSORS(Script, name, Object, kNameOffset)
5360 ACCESSORS(Script, id, Smi, kIdOffset)
5361 ACCESSORS_TO_SMI(Script, line_offset, kLineOffsetOffset)
5362 ACCESSORS_TO_SMI(Script, column_offset, kColumnOffsetOffset)
5363 ACCESSORS(Script, context_data, Object, kContextOffset)
5364 ACCESSORS(Script, wrapper, Foreign, kWrapperOffset)
5365 ACCESSORS_TO_SMI(Script, type, kTypeOffset)
5366 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
5367 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
5368 ACCESSORS_TO_SMI(Script, eval_from_instructions_offset,
5369 kEvalFrominstructionsOffsetOffset)
5370 ACCESSORS_TO_SMI(Script, flags, kFlagsOffset)
5371 BOOL_ACCESSORS(Script, flags, is_shared_cross_origin, kIsSharedCrossOriginBit)
5372 ACCESSORS(Script, source_url, Object, kSourceUrlOffset)
5373 ACCESSORS(Script, source_mapping_url, Object, kSourceMappingUrlOffset)
5374
5375 Script::CompilationType Script::compilation_type() {
5376 return BooleanBit::get(flags(), kCompilationTypeBit) ?
5377 COMPILATION_TYPE_EVAL : COMPILATION_TYPE_HOST;
5378 }
set_compilation_type(CompilationType type)5379 void Script::set_compilation_type(CompilationType type) {
5380 set_flags(BooleanBit::set(flags(), kCompilationTypeBit,
5381 type == COMPILATION_TYPE_EVAL));
5382 }
compilation_state()5383 Script::CompilationState Script::compilation_state() {
5384 return BooleanBit::get(flags(), kCompilationStateBit) ?
5385 COMPILATION_STATE_COMPILED : COMPILATION_STATE_INITIAL;
5386 }
set_compilation_state(CompilationState state)5387 void Script::set_compilation_state(CompilationState state) {
5388 set_flags(BooleanBit::set(flags(), kCompilationStateBit,
5389 state == COMPILATION_STATE_COMPILED));
5390 }
5391
5392
ACCESSORS(DebugInfo,shared,SharedFunctionInfo,kSharedFunctionInfoIndex)5393 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
5394 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
5395 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
5396 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
5397
5398 ACCESSORS_TO_SMI(BreakPointInfo, code_position, kCodePositionIndex)
5399 ACCESSORS_TO_SMI(BreakPointInfo, source_position, kSourcePositionIndex)
5400 ACCESSORS_TO_SMI(BreakPointInfo, statement_position, kStatementPositionIndex)
5401 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
5402
5403 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
5404 ACCESSORS(SharedFunctionInfo, optimized_code_map, Object,
5405 kOptimizedCodeMapOffset)
5406 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
5407 ACCESSORS(SharedFunctionInfo, feedback_vector, TypeFeedbackVector,
5408 kFeedbackVectorOffset)
5409 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
5410 kInstanceClassNameOffset)
5411 ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
5412 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
5413 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
5414 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
5415
5416
5417 SMI_ACCESSORS(FunctionTemplateInfo, length, kLengthOffset)
5418 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
5419 kHiddenPrototypeBit)
5420 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
5421 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
5422 kNeedsAccessCheckBit)
5423 BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
5424 kReadOnlyPrototypeBit)
5425 BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype,
5426 kRemovePrototypeBit)
5427 BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache,
5428 kDoNotCacheBit)
5429 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
5430 kIsExpressionBit)
5431 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
5432 kIsTopLevelBit)
5433
5434 BOOL_ACCESSORS(SharedFunctionInfo,
5435 compiler_hints,
5436 allows_lazy_compilation,
5437 kAllowLazyCompilation)
5438 BOOL_ACCESSORS(SharedFunctionInfo,
5439 compiler_hints,
5440 allows_lazy_compilation_without_context,
5441 kAllowLazyCompilationWithoutContext)
5442 BOOL_ACCESSORS(SharedFunctionInfo,
5443 compiler_hints,
5444 uses_arguments,
5445 kUsesArguments)
5446 BOOL_ACCESSORS(SharedFunctionInfo,
5447 compiler_hints,
5448 has_duplicate_parameters,
5449 kHasDuplicateParameters)
5450 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, asm_function, kIsAsmFunction)
5451
5452
5453 #if V8_HOST_ARCH_32_BIT
5454 SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
5455 SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
5456 kFormalParameterCountOffset)
5457 SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
5458 kExpectedNofPropertiesOffset)
5459 SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
5460 SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
5461 kStartPositionAndTypeOffset)
5462 SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
5463 SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
5464 kFunctionTokenPositionOffset)
5465 SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
5466 kCompilerHintsOffset)
5467 SMI_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason,
5468 kOptCountAndBailoutReasonOffset)
5469 SMI_ACCESSORS(SharedFunctionInfo, counters, kCountersOffset)
5470 SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
5471 SMI_ACCESSORS(SharedFunctionInfo, profiler_ticks, kProfilerTicksOffset)
5472
5473 #else
5474
5475 #define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
5476 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
5477 int holder::name() const { \
5478 int value = READ_INT_FIELD(this, offset); \
5479 DCHECK(kHeapObjectTag == 1); \
5480 DCHECK((value & kHeapObjectTag) == 0); \
5481 return value >> 1; \
5482 } \
5483 void holder::set_##name(int value) { \
5484 DCHECK(kHeapObjectTag == 1); \
5485 DCHECK((value & 0xC0000000) == 0xC0000000 || \
5486 (value & 0xC0000000) == 0x0); \
5487 WRITE_INT_FIELD(this, \
5488 offset, \
5489 (value << 1) & ~kHeapObjectTag); \
5490 }
5491
5492 #define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
5493 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
5494 INT_ACCESSORS(holder, name, offset)
5495
5496
5497 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
5498 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5499 formal_parameter_count,
5500 kFormalParameterCountOffset)
5501
5502 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
5503 expected_nof_properties,
5504 kExpectedNofPropertiesOffset)
5505 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
5506
5507 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
5508 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5509 start_position_and_type,
5510 kStartPositionAndTypeOffset)
5511
5512 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
5513 function_token_position,
5514 kFunctionTokenPositionOffset)
5515 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5516 compiler_hints,
5517 kCompilerHintsOffset)
5518
5519 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
5520 opt_count_and_bailout_reason,
5521 kOptCountAndBailoutReasonOffset)
5522 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, counters, kCountersOffset)
5523
5524 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
5525 ast_node_count,
5526 kAstNodeCountOffset)
5527 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5528 profiler_ticks,
5529 kProfilerTicksOffset)
5530
5531 #endif
5532
5533
5534 BOOL_GETTER(SharedFunctionInfo,
5535 compiler_hints,
5536 optimization_disabled,
5537 kOptimizationDisabled)
5538
5539
5540 void SharedFunctionInfo::set_optimization_disabled(bool disable) {
5541 set_compiler_hints(BooleanBit::set(compiler_hints(),
5542 kOptimizationDisabled,
5543 disable));
5544 // If disabling optimizations we reflect that in the code object so
5545 // it will not be counted as optimizable code.
5546 if ((code()->kind() == Code::FUNCTION) && disable) {
5547 code()->set_optimizable(false);
5548 }
5549 }
5550
5551
strict_mode()5552 StrictMode SharedFunctionInfo::strict_mode() {
5553 return BooleanBit::get(compiler_hints(), kStrictModeFunction)
5554 ? STRICT : SLOPPY;
5555 }
5556
5557
set_strict_mode(StrictMode strict_mode)5558 void SharedFunctionInfo::set_strict_mode(StrictMode strict_mode) {
5559 // We only allow mode transitions from sloppy to strict.
5560 DCHECK(this->strict_mode() == SLOPPY || this->strict_mode() == strict_mode);
5561 int hints = compiler_hints();
5562 hints = BooleanBit::set(hints, kStrictModeFunction, strict_mode == STRICT);
5563 set_compiler_hints(hints);
5564 }
5565
5566
kind()5567 FunctionKind SharedFunctionInfo::kind() {
5568 return FunctionKindBits::decode(compiler_hints());
5569 }
5570
5571
set_kind(FunctionKind kind)5572 void SharedFunctionInfo::set_kind(FunctionKind kind) {
5573 DCHECK(IsValidFunctionKind(kind));
5574 int hints = compiler_hints();
5575 hints = FunctionKindBits::update(hints, kind);
5576 set_compiler_hints(hints);
5577 }
5578
5579
BOOL_ACCESSORS(SharedFunctionInfo,compiler_hints,native,kNative)5580 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
5581 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, inline_builtin,
5582 kInlineBuiltin)
5583 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
5584 name_should_print_as_anonymous,
5585 kNameShouldPrintAsAnonymous)
5586 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
5587 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
5588 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
5589 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_cache, kDontCache)
5590 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush)
5591 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_arrow, kIsArrow)
5592 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
5593 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_concise_method,
5594 kIsConciseMethod)
5595
5596 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
5597 ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
5598
5599 ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
5600
5601 bool Script::HasValidSource() {
5602 Object* src = this->source();
5603 if (!src->IsString()) return true;
5604 String* src_str = String::cast(src);
5605 if (!StringShape(src_str).IsExternal()) return true;
5606 if (src_str->IsOneByteRepresentation()) {
5607 return ExternalOneByteString::cast(src)->resource() != NULL;
5608 } else if (src_str->IsTwoByteRepresentation()) {
5609 return ExternalTwoByteString::cast(src)->resource() != NULL;
5610 }
5611 return true;
5612 }
5613
5614
DontAdaptArguments()5615 void SharedFunctionInfo::DontAdaptArguments() {
5616 DCHECK(code()->kind() == Code::BUILTIN);
5617 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
5618 }
5619
5620
start_position()5621 int SharedFunctionInfo::start_position() const {
5622 return start_position_and_type() >> kStartPositionShift;
5623 }
5624
5625
set_start_position(int start_position)5626 void SharedFunctionInfo::set_start_position(int start_position) {
5627 set_start_position_and_type((start_position << kStartPositionShift)
5628 | (start_position_and_type() & ~kStartPositionMask));
5629 }
5630
5631
code()5632 Code* SharedFunctionInfo::code() const {
5633 return Code::cast(READ_FIELD(this, kCodeOffset));
5634 }
5635
5636
set_code(Code * value,WriteBarrierMode mode)5637 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
5638 DCHECK(value->kind() != Code::OPTIMIZED_FUNCTION);
5639 WRITE_FIELD(this, kCodeOffset, value);
5640 CONDITIONAL_WRITE_BARRIER(value->GetHeap(), this, kCodeOffset, value, mode);
5641 }
5642
5643
ReplaceCode(Code * value)5644 void SharedFunctionInfo::ReplaceCode(Code* value) {
5645 // If the GC metadata field is already used then the function was
5646 // enqueued as a code flushing candidate and we remove it now.
5647 if (code()->gc_metadata() != NULL) {
5648 CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
5649 flusher->EvictCandidate(this);
5650 }
5651
5652 DCHECK(code()->gc_metadata() == NULL && value->gc_metadata() == NULL);
5653
5654 set_code(value);
5655 }
5656
5657
scope_info()5658 ScopeInfo* SharedFunctionInfo::scope_info() const {
5659 return reinterpret_cast<ScopeInfo*>(READ_FIELD(this, kScopeInfoOffset));
5660 }
5661
5662
set_scope_info(ScopeInfo * value,WriteBarrierMode mode)5663 void SharedFunctionInfo::set_scope_info(ScopeInfo* value,
5664 WriteBarrierMode mode) {
5665 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
5666 CONDITIONAL_WRITE_BARRIER(GetHeap(),
5667 this,
5668 kScopeInfoOffset,
5669 reinterpret_cast<Object*>(value),
5670 mode);
5671 }
5672
5673
is_compiled()5674 bool SharedFunctionInfo::is_compiled() {
5675 return code() != GetIsolate()->builtins()->builtin(Builtins::kCompileLazy);
5676 }
5677
5678
IsApiFunction()5679 bool SharedFunctionInfo::IsApiFunction() {
5680 return function_data()->IsFunctionTemplateInfo();
5681 }
5682
5683
get_api_func_data()5684 FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
5685 DCHECK(IsApiFunction());
5686 return FunctionTemplateInfo::cast(function_data());
5687 }
5688
5689
HasBuiltinFunctionId()5690 bool SharedFunctionInfo::HasBuiltinFunctionId() {
5691 return function_data()->IsSmi();
5692 }
5693
5694
builtin_function_id()5695 BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
5696 DCHECK(HasBuiltinFunctionId());
5697 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
5698 }
5699
5700
ic_age()5701 int SharedFunctionInfo::ic_age() {
5702 return ICAgeBits::decode(counters());
5703 }
5704
5705
set_ic_age(int ic_age)5706 void SharedFunctionInfo::set_ic_age(int ic_age) {
5707 set_counters(ICAgeBits::update(counters(), ic_age));
5708 }
5709
5710
deopt_count()5711 int SharedFunctionInfo::deopt_count() {
5712 return DeoptCountBits::decode(counters());
5713 }
5714
5715
set_deopt_count(int deopt_count)5716 void SharedFunctionInfo::set_deopt_count(int deopt_count) {
5717 set_counters(DeoptCountBits::update(counters(), deopt_count));
5718 }
5719
5720
increment_deopt_count()5721 void SharedFunctionInfo::increment_deopt_count() {
5722 int value = counters();
5723 int deopt_count = DeoptCountBits::decode(value);
5724 deopt_count = (deopt_count + 1) & DeoptCountBits::kMax;
5725 set_counters(DeoptCountBits::update(value, deopt_count));
5726 }
5727
5728
opt_reenable_tries()5729 int SharedFunctionInfo::opt_reenable_tries() {
5730 return OptReenableTriesBits::decode(counters());
5731 }
5732
5733
set_opt_reenable_tries(int tries)5734 void SharedFunctionInfo::set_opt_reenable_tries(int tries) {
5735 set_counters(OptReenableTriesBits::update(counters(), tries));
5736 }
5737
5738
opt_count()5739 int SharedFunctionInfo::opt_count() {
5740 return OptCountBits::decode(opt_count_and_bailout_reason());
5741 }
5742
5743
set_opt_count(int opt_count)5744 void SharedFunctionInfo::set_opt_count(int opt_count) {
5745 set_opt_count_and_bailout_reason(
5746 OptCountBits::update(opt_count_and_bailout_reason(), opt_count));
5747 }
5748
5749
DisableOptimizationReason()5750 BailoutReason SharedFunctionInfo::DisableOptimizationReason() {
5751 BailoutReason reason = static_cast<BailoutReason>(
5752 DisabledOptimizationReasonBits::decode(opt_count_and_bailout_reason()));
5753 return reason;
5754 }
5755
5756
has_deoptimization_support()5757 bool SharedFunctionInfo::has_deoptimization_support() {
5758 Code* code = this->code();
5759 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
5760 }
5761
5762
TryReenableOptimization()5763 void SharedFunctionInfo::TryReenableOptimization() {
5764 int tries = opt_reenable_tries();
5765 set_opt_reenable_tries((tries + 1) & OptReenableTriesBits::kMax);
5766 // We reenable optimization whenever the number of tries is a large
5767 // enough power of 2.
5768 if (tries >= 16 && (((tries - 1) & tries) == 0)) {
5769 set_optimization_disabled(false);
5770 set_opt_count(0);
5771 set_deopt_count(0);
5772 code()->set_optimizable(true);
5773 }
5774 }
5775
5776
IsBuiltin()5777 bool JSFunction::IsBuiltin() {
5778 return context()->global_object()->IsJSBuiltinsObject();
5779 }
5780
5781
IsFromNativeScript()5782 bool JSFunction::IsFromNativeScript() {
5783 Object* script = shared()->script();
5784 bool native = script->IsScript() &&
5785 Script::cast(script)->type()->value() == Script::TYPE_NATIVE;
5786 DCHECK(!IsBuiltin() || native); // All builtins are also native.
5787 return native;
5788 }
5789
5790
IsFromExtensionScript()5791 bool JSFunction::IsFromExtensionScript() {
5792 Object* script = shared()->script();
5793 return script->IsScript() &&
5794 Script::cast(script)->type()->value() == Script::TYPE_EXTENSION;
5795 }
5796
5797
NeedsArgumentsAdaption()5798 bool JSFunction::NeedsArgumentsAdaption() {
5799 return shared()->formal_parameter_count() !=
5800 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
5801 }
5802
5803
IsOptimized()5804 bool JSFunction::IsOptimized() {
5805 return code()->kind() == Code::OPTIMIZED_FUNCTION;
5806 }
5807
5808
IsOptimizable()5809 bool JSFunction::IsOptimizable() {
5810 return code()->kind() == Code::FUNCTION && code()->optimizable();
5811 }
5812
5813
IsMarkedForOptimization()5814 bool JSFunction::IsMarkedForOptimization() {
5815 return code() == GetIsolate()->builtins()->builtin(
5816 Builtins::kCompileOptimized);
5817 }
5818
5819
IsMarkedForConcurrentOptimization()5820 bool JSFunction::IsMarkedForConcurrentOptimization() {
5821 return code() == GetIsolate()->builtins()->builtin(
5822 Builtins::kCompileOptimizedConcurrent);
5823 }
5824
5825
IsInOptimizationQueue()5826 bool JSFunction::IsInOptimizationQueue() {
5827 return code() == GetIsolate()->builtins()->builtin(
5828 Builtins::kInOptimizationQueue);
5829 }
5830
5831
IsInobjectSlackTrackingInProgress()5832 bool JSFunction::IsInobjectSlackTrackingInProgress() {
5833 return has_initial_map() &&
5834 initial_map()->construction_count() != JSFunction::kNoSlackTracking;
5835 }
5836
5837
code()5838 Code* JSFunction::code() {
5839 return Code::cast(
5840 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
5841 }
5842
5843
set_code(Code * value)5844 void JSFunction::set_code(Code* value) {
5845 DCHECK(!GetHeap()->InNewSpace(value));
5846 Address entry = value->entry();
5847 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
5848 GetHeap()->incremental_marking()->RecordWriteOfCodeEntry(
5849 this,
5850 HeapObject::RawField(this, kCodeEntryOffset),
5851 value);
5852 }
5853
5854
set_code_no_write_barrier(Code * value)5855 void JSFunction::set_code_no_write_barrier(Code* value) {
5856 DCHECK(!GetHeap()->InNewSpace(value));
5857 Address entry = value->entry();
5858 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
5859 }
5860
5861
ReplaceCode(Code * code)5862 void JSFunction::ReplaceCode(Code* code) {
5863 bool was_optimized = IsOptimized();
5864 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
5865
5866 if (was_optimized && is_optimized) {
5867 shared()->EvictFromOptimizedCodeMap(this->code(),
5868 "Replacing with another optimized code");
5869 }
5870
5871 set_code(code);
5872
5873 // Add/remove the function from the list of optimized functions for this
5874 // context based on the state change.
5875 if (!was_optimized && is_optimized) {
5876 context()->native_context()->AddOptimizedFunction(this);
5877 }
5878 if (was_optimized && !is_optimized) {
5879 // TODO(titzer): linear in the number of optimized functions; fix!
5880 context()->native_context()->RemoveOptimizedFunction(this);
5881 }
5882 }
5883
5884
context()5885 Context* JSFunction::context() {
5886 return Context::cast(READ_FIELD(this, kContextOffset));
5887 }
5888
5889
global_proxy()5890 JSObject* JSFunction::global_proxy() {
5891 return context()->global_proxy();
5892 }
5893
5894
set_context(Object * value)5895 void JSFunction::set_context(Object* value) {
5896 DCHECK(value->IsUndefined() || value->IsContext());
5897 WRITE_FIELD(this, kContextOffset, value);
5898 WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
5899 }
5900
ACCESSORS(JSFunction,prototype_or_initial_map,Object,kPrototypeOrInitialMapOffset)5901 ACCESSORS(JSFunction, prototype_or_initial_map, Object,
5902 kPrototypeOrInitialMapOffset)
5903
5904
5905 Map* JSFunction::initial_map() {
5906 return Map::cast(prototype_or_initial_map());
5907 }
5908
5909
has_initial_map()5910 bool JSFunction::has_initial_map() {
5911 return prototype_or_initial_map()->IsMap();
5912 }
5913
5914
has_instance_prototype()5915 bool JSFunction::has_instance_prototype() {
5916 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
5917 }
5918
5919
has_prototype()5920 bool JSFunction::has_prototype() {
5921 return map()->has_non_instance_prototype() || has_instance_prototype();
5922 }
5923
5924
instance_prototype()5925 Object* JSFunction::instance_prototype() {
5926 DCHECK(has_instance_prototype());
5927 if (has_initial_map()) return initial_map()->prototype();
5928 // When there is no initial map and the prototype is a JSObject, the
5929 // initial map field is used for the prototype field.
5930 return prototype_or_initial_map();
5931 }
5932
5933
prototype()5934 Object* JSFunction::prototype() {
5935 DCHECK(has_prototype());
5936 // If the function's prototype property has been set to a non-JSObject
5937 // value, that value is stored in the constructor field of the map.
5938 if (map()->has_non_instance_prototype()) return map()->constructor();
5939 return instance_prototype();
5940 }
5941
5942
should_have_prototype()5943 bool JSFunction::should_have_prototype() {
5944 return map()->function_with_prototype();
5945 }
5946
5947
is_compiled()5948 bool JSFunction::is_compiled() {
5949 return code() != GetIsolate()->builtins()->builtin(Builtins::kCompileLazy);
5950 }
5951
5952
literals()5953 FixedArray* JSFunction::literals() {
5954 DCHECK(!shared()->bound());
5955 return literals_or_bindings();
5956 }
5957
5958
set_literals(FixedArray * literals)5959 void JSFunction::set_literals(FixedArray* literals) {
5960 DCHECK(!shared()->bound());
5961 set_literals_or_bindings(literals);
5962 }
5963
5964
function_bindings()5965 FixedArray* JSFunction::function_bindings() {
5966 DCHECK(shared()->bound());
5967 return literals_or_bindings();
5968 }
5969
5970
set_function_bindings(FixedArray * bindings)5971 void JSFunction::set_function_bindings(FixedArray* bindings) {
5972 DCHECK(shared()->bound());
5973 // Bound function literal may be initialized to the empty fixed array
5974 // before the bindings are set.
5975 DCHECK(bindings == GetHeap()->empty_fixed_array() ||
5976 bindings->map() == GetHeap()->fixed_cow_array_map());
5977 set_literals_or_bindings(bindings);
5978 }
5979
5980
NumberOfLiterals()5981 int JSFunction::NumberOfLiterals() {
5982 DCHECK(!shared()->bound());
5983 return literals()->length();
5984 }
5985
5986
javascript_builtin(Builtins::JavaScript id)5987 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
5988 DCHECK(id < kJSBuiltinsCount); // id is unsigned.
5989 return READ_FIELD(this, OffsetOfFunctionWithId(id));
5990 }
5991
5992
set_javascript_builtin(Builtins::JavaScript id,Object * value)5993 void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
5994 Object* value) {
5995 DCHECK(id < kJSBuiltinsCount); // id is unsigned.
5996 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
5997 WRITE_BARRIER(GetHeap(), this, OffsetOfFunctionWithId(id), value);
5998 }
5999
6000
javascript_builtin_code(Builtins::JavaScript id)6001 Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
6002 DCHECK(id < kJSBuiltinsCount); // id is unsigned.
6003 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
6004 }
6005
6006
set_javascript_builtin_code(Builtins::JavaScript id,Code * value)6007 void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
6008 Code* value) {
6009 DCHECK(id < kJSBuiltinsCount); // id is unsigned.
6010 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
6011 DCHECK(!GetHeap()->InNewSpace(value));
6012 }
6013
6014
ACCESSORS(JSProxy,handler,Object,kHandlerOffset)6015 ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
6016 ACCESSORS(JSProxy, hash, Object, kHashOffset)
6017 ACCESSORS(JSFunctionProxy, call_trap, Object, kCallTrapOffset)
6018 ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
6019
6020
6021 void JSProxy::InitializeBody(int object_size, Object* value) {
6022 DCHECK(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
6023 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
6024 WRITE_FIELD(this, offset, value);
6025 }
6026 }
6027
6028
ACCESSORS(JSCollection,table,Object,kTableOffset)6029 ACCESSORS(JSCollection, table, Object, kTableOffset)
6030
6031
6032 #define ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(name, type, offset) \
6033 template<class Derived, class TableType> \
6034 type* OrderedHashTableIterator<Derived, TableType>::name() const { \
6035 return type::cast(READ_FIELD(this, offset)); \
6036 } \
6037 template<class Derived, class TableType> \
6038 void OrderedHashTableIterator<Derived, TableType>::set_##name( \
6039 type* value, WriteBarrierMode mode) { \
6040 WRITE_FIELD(this, offset, value); \
6041 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \
6042 }
6043
6044 ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(table, Object, kTableOffset)
6045 ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(index, Object, kIndexOffset)
6046 ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(kind, Object, kKindOffset)
6047
6048 #undef ORDERED_HASH_TABLE_ITERATOR_ACCESSORS
6049
6050
6051 ACCESSORS(JSWeakCollection, table, Object, kTableOffset)
6052 ACCESSORS(JSWeakCollection, next, Object, kNextOffset)
6053
6054
6055 Address Foreign::foreign_address() {
6056 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset));
6057 }
6058
6059
set_foreign_address(Address value)6060 void Foreign::set_foreign_address(Address value) {
6061 WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value));
6062 }
6063
6064
ACCESSORS(JSGeneratorObject,function,JSFunction,kFunctionOffset)6065 ACCESSORS(JSGeneratorObject, function, JSFunction, kFunctionOffset)
6066 ACCESSORS(JSGeneratorObject, context, Context, kContextOffset)
6067 ACCESSORS(JSGeneratorObject, receiver, Object, kReceiverOffset)
6068 SMI_ACCESSORS(JSGeneratorObject, continuation, kContinuationOffset)
6069 ACCESSORS(JSGeneratorObject, operand_stack, FixedArray, kOperandStackOffset)
6070 SMI_ACCESSORS(JSGeneratorObject, stack_handler_index, kStackHandlerIndexOffset)
6071
6072 bool JSGeneratorObject::is_suspended() {
6073 DCHECK_LT(kGeneratorExecuting, kGeneratorClosed);
6074 DCHECK_EQ(kGeneratorClosed, 0);
6075 return continuation() > 0;
6076 }
6077
is_closed()6078 bool JSGeneratorObject::is_closed() {
6079 return continuation() == kGeneratorClosed;
6080 }
6081
is_executing()6082 bool JSGeneratorObject::is_executing() {
6083 return continuation() == kGeneratorExecuting;
6084 }
6085
ACCESSORS(JSModule,context,Object,kContextOffset)6086 ACCESSORS(JSModule, context, Object, kContextOffset)
6087 ACCESSORS(JSModule, scope_info, ScopeInfo, kScopeInfoOffset)
6088
6089
6090 ACCESSORS(JSValue, value, Object, kValueOffset)
6091
6092
6093 HeapNumber* HeapNumber::cast(Object* object) {
6094 SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber());
6095 return reinterpret_cast<HeapNumber*>(object);
6096 }
6097
6098
cast(const Object * object)6099 const HeapNumber* HeapNumber::cast(const Object* object) {
6100 SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber());
6101 return reinterpret_cast<const HeapNumber*>(object);
6102 }
6103
6104
ACCESSORS(JSDate,value,Object,kValueOffset)6105 ACCESSORS(JSDate, value, Object, kValueOffset)
6106 ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset)
6107 ACCESSORS(JSDate, year, Object, kYearOffset)
6108 ACCESSORS(JSDate, month, Object, kMonthOffset)
6109 ACCESSORS(JSDate, day, Object, kDayOffset)
6110 ACCESSORS(JSDate, weekday, Object, kWeekdayOffset)
6111 ACCESSORS(JSDate, hour, Object, kHourOffset)
6112 ACCESSORS(JSDate, min, Object, kMinOffset)
6113 ACCESSORS(JSDate, sec, Object, kSecOffset)
6114
6115
6116 ACCESSORS(JSMessageObject, type, String, kTypeOffset)
6117 ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
6118 ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
6119 ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
6120 SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
6121 SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
6122
6123
6124 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
6125 INT_ACCESSORS(Code, prologue_offset, kPrologueOffset)
6126 ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
6127 ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
6128 ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
6129 ACCESSORS(Code, raw_type_feedback_info, Object, kTypeFeedbackInfoOffset)
6130 ACCESSORS(Code, next_code_link, Object, kNextCodeLinkOffset)
6131
6132
6133 void Code::WipeOutHeader() {
6134 WRITE_FIELD(this, kRelocationInfoOffset, NULL);
6135 WRITE_FIELD(this, kHandlerTableOffset, NULL);
6136 WRITE_FIELD(this, kDeoptimizationDataOffset, NULL);
6137 WRITE_FIELD(this, kConstantPoolOffset, NULL);
6138 // Do not wipe out major/minor keys on a code stub or IC
6139 if (!READ_FIELD(this, kTypeFeedbackInfoOffset)->IsSmi()) {
6140 WRITE_FIELD(this, kTypeFeedbackInfoOffset, NULL);
6141 }
6142 }
6143
6144
type_feedback_info()6145 Object* Code::type_feedback_info() {
6146 DCHECK(kind() == FUNCTION);
6147 return raw_type_feedback_info();
6148 }
6149
6150
set_type_feedback_info(Object * value,WriteBarrierMode mode)6151 void Code::set_type_feedback_info(Object* value, WriteBarrierMode mode) {
6152 DCHECK(kind() == FUNCTION);
6153 set_raw_type_feedback_info(value, mode);
6154 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTypeFeedbackInfoOffset,
6155 value, mode);
6156 }
6157
6158
stub_key()6159 uint32_t Code::stub_key() {
6160 DCHECK(IsCodeStubOrIC());
6161 Smi* smi_key = Smi::cast(raw_type_feedback_info());
6162 return static_cast<uint32_t>(smi_key->value());
6163 }
6164
6165
set_stub_key(uint32_t key)6166 void Code::set_stub_key(uint32_t key) {
6167 DCHECK(IsCodeStubOrIC());
6168 set_raw_type_feedback_info(Smi::FromInt(key));
6169 }
6170
6171
ACCESSORS(Code,gc_metadata,Object,kGCMetadataOffset)6172 ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
6173 INT_ACCESSORS(Code, ic_age, kICAgeOffset)
6174
6175
6176 byte* Code::instruction_start() {
6177 return FIELD_ADDR(this, kHeaderSize);
6178 }
6179
6180
instruction_end()6181 byte* Code::instruction_end() {
6182 return instruction_start() + instruction_size();
6183 }
6184
6185
body_size()6186 int Code::body_size() {
6187 return RoundUp(instruction_size(), kObjectAlignment);
6188 }
6189
6190
unchecked_relocation_info()6191 ByteArray* Code::unchecked_relocation_info() {
6192 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
6193 }
6194
6195
relocation_start()6196 byte* Code::relocation_start() {
6197 return unchecked_relocation_info()->GetDataStartAddress();
6198 }
6199
6200
relocation_size()6201 int Code::relocation_size() {
6202 return unchecked_relocation_info()->length();
6203 }
6204
6205
entry()6206 byte* Code::entry() {
6207 return instruction_start();
6208 }
6209
6210
contains(byte * inner_pointer)6211 bool Code::contains(byte* inner_pointer) {
6212 return (address() <= inner_pointer) && (inner_pointer <= address() + Size());
6213 }
6214
6215
ACCESSORS(JSArray,length,Object,kLengthOffset)6216 ACCESSORS(JSArray, length, Object, kLengthOffset)
6217
6218
6219 void* JSArrayBuffer::backing_store() const {
6220 intptr_t ptr = READ_INTPTR_FIELD(this, kBackingStoreOffset);
6221 return reinterpret_cast<void*>(ptr);
6222 }
6223
6224
set_backing_store(void * value,WriteBarrierMode mode)6225 void JSArrayBuffer::set_backing_store(void* value, WriteBarrierMode mode) {
6226 intptr_t ptr = reinterpret_cast<intptr_t>(value);
6227 WRITE_INTPTR_FIELD(this, kBackingStoreOffset, ptr);
6228 }
6229
6230
ACCESSORS(JSArrayBuffer,byte_length,Object,kByteLengthOffset)6231 ACCESSORS(JSArrayBuffer, byte_length, Object, kByteLengthOffset)
6232 ACCESSORS_TO_SMI(JSArrayBuffer, flag, kFlagOffset)
6233
6234
6235 bool JSArrayBuffer::is_external() {
6236 return BooleanBit::get(flag(), kIsExternalBit);
6237 }
6238
6239
set_is_external(bool value)6240 void JSArrayBuffer::set_is_external(bool value) {
6241 set_flag(BooleanBit::set(flag(), kIsExternalBit, value));
6242 }
6243
6244
should_be_freed()6245 bool JSArrayBuffer::should_be_freed() {
6246 return BooleanBit::get(flag(), kShouldBeFreed);
6247 }
6248
6249
set_should_be_freed(bool value)6250 void JSArrayBuffer::set_should_be_freed(bool value) {
6251 set_flag(BooleanBit::set(flag(), kShouldBeFreed, value));
6252 }
6253
6254
ACCESSORS(JSArrayBuffer,weak_next,Object,kWeakNextOffset)6255 ACCESSORS(JSArrayBuffer, weak_next, Object, kWeakNextOffset)
6256 ACCESSORS(JSArrayBuffer, weak_first_view, Object, kWeakFirstViewOffset)
6257
6258
6259 ACCESSORS(JSArrayBufferView, buffer, Object, kBufferOffset)
6260 ACCESSORS(JSArrayBufferView, byte_offset, Object, kByteOffsetOffset)
6261 ACCESSORS(JSArrayBufferView, byte_length, Object, kByteLengthOffset)
6262 ACCESSORS(JSArrayBufferView, weak_next, Object, kWeakNextOffset)
6263 ACCESSORS(JSTypedArray, length, Object, kLengthOffset)
6264
6265 ACCESSORS(JSRegExp, data, Object, kDataOffset)
6266
6267
6268 JSRegExp::Type JSRegExp::TypeTag() {
6269 Object* data = this->data();
6270 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
6271 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
6272 return static_cast<JSRegExp::Type>(smi->value());
6273 }
6274
6275
CaptureCount()6276 int JSRegExp::CaptureCount() {
6277 switch (TypeTag()) {
6278 case ATOM:
6279 return 0;
6280 case IRREGEXP:
6281 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
6282 default:
6283 UNREACHABLE();
6284 return -1;
6285 }
6286 }
6287
6288
GetFlags()6289 JSRegExp::Flags JSRegExp::GetFlags() {
6290 DCHECK(this->data()->IsFixedArray());
6291 Object* data = this->data();
6292 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
6293 return Flags(smi->value());
6294 }
6295
6296
Pattern()6297 String* JSRegExp::Pattern() {
6298 DCHECK(this->data()->IsFixedArray());
6299 Object* data = this->data();
6300 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
6301 return pattern;
6302 }
6303
6304
DataAt(int index)6305 Object* JSRegExp::DataAt(int index) {
6306 DCHECK(TypeTag() != NOT_COMPILED);
6307 return FixedArray::cast(data())->get(index);
6308 }
6309
6310
SetDataAt(int index,Object * value)6311 void JSRegExp::SetDataAt(int index, Object* value) {
6312 DCHECK(TypeTag() != NOT_COMPILED);
6313 DCHECK(index >= kDataIndex); // Only implementation data can be set this way.
6314 FixedArray::cast(data())->set(index, value);
6315 }
6316
6317
GetElementsKind()6318 ElementsKind JSObject::GetElementsKind() {
6319 ElementsKind kind = map()->elements_kind();
6320 #if DEBUG
6321 FixedArrayBase* fixed_array =
6322 reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset));
6323
6324 // If a GC was caused while constructing this object, the elements
6325 // pointer may point to a one pointer filler map.
6326 if (ElementsAreSafeToExamine()) {
6327 Map* map = fixed_array->map();
6328 DCHECK((IsFastSmiOrObjectElementsKind(kind) &&
6329 (map == GetHeap()->fixed_array_map() ||
6330 map == GetHeap()->fixed_cow_array_map())) ||
6331 (IsFastDoubleElementsKind(kind) &&
6332 (fixed_array->IsFixedDoubleArray() ||
6333 fixed_array == GetHeap()->empty_fixed_array())) ||
6334 (kind == DICTIONARY_ELEMENTS &&
6335 fixed_array->IsFixedArray() &&
6336 fixed_array->IsDictionary()) ||
6337 (kind > DICTIONARY_ELEMENTS));
6338 DCHECK((kind != SLOPPY_ARGUMENTS_ELEMENTS) ||
6339 (elements()->IsFixedArray() && elements()->length() >= 2));
6340 }
6341 #endif
6342 return kind;
6343 }
6344
6345
GetElementsAccessor()6346 ElementsAccessor* JSObject::GetElementsAccessor() {
6347 return ElementsAccessor::ForKind(GetElementsKind());
6348 }
6349
6350
HasFastObjectElements()6351 bool JSObject::HasFastObjectElements() {
6352 return IsFastObjectElementsKind(GetElementsKind());
6353 }
6354
6355
HasFastSmiElements()6356 bool JSObject::HasFastSmiElements() {
6357 return IsFastSmiElementsKind(GetElementsKind());
6358 }
6359
6360
HasFastSmiOrObjectElements()6361 bool JSObject::HasFastSmiOrObjectElements() {
6362 return IsFastSmiOrObjectElementsKind(GetElementsKind());
6363 }
6364
6365
HasFastDoubleElements()6366 bool JSObject::HasFastDoubleElements() {
6367 return IsFastDoubleElementsKind(GetElementsKind());
6368 }
6369
6370
HasFastHoleyElements()6371 bool JSObject::HasFastHoleyElements() {
6372 return IsFastHoleyElementsKind(GetElementsKind());
6373 }
6374
6375
HasFastElements()6376 bool JSObject::HasFastElements() {
6377 return IsFastElementsKind(GetElementsKind());
6378 }
6379
6380
HasDictionaryElements()6381 bool JSObject::HasDictionaryElements() {
6382 return GetElementsKind() == DICTIONARY_ELEMENTS;
6383 }
6384
6385
HasSloppyArgumentsElements()6386 bool JSObject::HasSloppyArgumentsElements() {
6387 return GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS;
6388 }
6389
6390
HasExternalArrayElements()6391 bool JSObject::HasExternalArrayElements() {
6392 HeapObject* array = elements();
6393 DCHECK(array != NULL);
6394 return array->IsExternalArray();
6395 }
6396
6397
6398 #define EXTERNAL_ELEMENTS_CHECK(Type, type, TYPE, ctype, size) \
6399 bool JSObject::HasExternal##Type##Elements() { \
6400 HeapObject* array = elements(); \
6401 DCHECK(array != NULL); \
6402 if (!array->IsHeapObject()) \
6403 return false; \
6404 return array->map()->instance_type() == EXTERNAL_##TYPE##_ARRAY_TYPE; \
6405 }
6406
TYPED_ARRAYS(EXTERNAL_ELEMENTS_CHECK)6407 TYPED_ARRAYS(EXTERNAL_ELEMENTS_CHECK)
6408
6409 #undef EXTERNAL_ELEMENTS_CHECK
6410
6411
6412 bool JSObject::HasFixedTypedArrayElements() {
6413 HeapObject* array = elements();
6414 DCHECK(array != NULL);
6415 return array->IsFixedTypedArrayBase();
6416 }
6417
6418
6419 #define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype, size) \
6420 bool JSObject::HasFixed##Type##Elements() { \
6421 HeapObject* array = elements(); \
6422 DCHECK(array != NULL); \
6423 if (!array->IsHeapObject()) \
6424 return false; \
6425 return array->map()->instance_type() == FIXED_##TYPE##_ARRAY_TYPE; \
6426 }
6427
TYPED_ARRAYS(FIXED_TYPED_ELEMENTS_CHECK)6428 TYPED_ARRAYS(FIXED_TYPED_ELEMENTS_CHECK)
6429
6430 #undef FIXED_TYPED_ELEMENTS_CHECK
6431
6432
6433 bool JSObject::HasNamedInterceptor() {
6434 return map()->has_named_interceptor();
6435 }
6436
6437
HasIndexedInterceptor()6438 bool JSObject::HasIndexedInterceptor() {
6439 return map()->has_indexed_interceptor();
6440 }
6441
6442
property_dictionary()6443 NameDictionary* JSObject::property_dictionary() {
6444 DCHECK(!HasFastProperties());
6445 return NameDictionary::cast(properties());
6446 }
6447
6448
element_dictionary()6449 SeededNumberDictionary* JSObject::element_dictionary() {
6450 DCHECK(HasDictionaryElements());
6451 return SeededNumberDictionary::cast(elements());
6452 }
6453
6454
IsHashFieldComputed(uint32_t field)6455 bool Name::IsHashFieldComputed(uint32_t field) {
6456 return (field & kHashNotComputedMask) == 0;
6457 }
6458
6459
HasHashCode()6460 bool Name::HasHashCode() {
6461 return IsHashFieldComputed(hash_field());
6462 }
6463
6464
Hash()6465 uint32_t Name::Hash() {
6466 // Fast case: has hash code already been computed?
6467 uint32_t field = hash_field();
6468 if (IsHashFieldComputed(field)) return field >> kHashShift;
6469 // Slow case: compute hash code and set it. Has to be a string.
6470 return String::cast(this)->ComputeAndSetHash();
6471 }
6472
IsOwn()6473 bool Name::IsOwn() {
6474 return this->IsSymbol() && Symbol::cast(this)->is_own();
6475 }
6476
6477
StringHasher(int length,uint32_t seed)6478 StringHasher::StringHasher(int length, uint32_t seed)
6479 : length_(length),
6480 raw_running_hash_(seed),
6481 array_index_(0),
6482 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
6483 is_first_char_(true) {
6484 DCHECK(FLAG_randomize_hashes || raw_running_hash_ == 0);
6485 }
6486
6487
has_trivial_hash()6488 bool StringHasher::has_trivial_hash() {
6489 return length_ > String::kMaxHashCalcLength;
6490 }
6491
6492
AddCharacterCore(uint32_t running_hash,uint16_t c)6493 uint32_t StringHasher::AddCharacterCore(uint32_t running_hash, uint16_t c) {
6494 running_hash += c;
6495 running_hash += (running_hash << 10);
6496 running_hash ^= (running_hash >> 6);
6497 return running_hash;
6498 }
6499
6500
GetHashCore(uint32_t running_hash)6501 uint32_t StringHasher::GetHashCore(uint32_t running_hash) {
6502 running_hash += (running_hash << 3);
6503 running_hash ^= (running_hash >> 11);
6504 running_hash += (running_hash << 15);
6505 if ((running_hash & String::kHashBitMask) == 0) {
6506 return kZeroHash;
6507 }
6508 return running_hash;
6509 }
6510
6511
AddCharacter(uint16_t c)6512 void StringHasher::AddCharacter(uint16_t c) {
6513 // Use the Jenkins one-at-a-time hash function to update the hash
6514 // for the given character.
6515 raw_running_hash_ = AddCharacterCore(raw_running_hash_, c);
6516 }
6517
6518
UpdateIndex(uint16_t c)6519 bool StringHasher::UpdateIndex(uint16_t c) {
6520 DCHECK(is_array_index_);
6521 if (c < '0' || c > '9') {
6522 is_array_index_ = false;
6523 return false;
6524 }
6525 int d = c - '0';
6526 if (is_first_char_) {
6527 is_first_char_ = false;
6528 if (c == '0' && length_ > 1) {
6529 is_array_index_ = false;
6530 return false;
6531 }
6532 }
6533 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
6534 is_array_index_ = false;
6535 return false;
6536 }
6537 array_index_ = array_index_ * 10 + d;
6538 return true;
6539 }
6540
6541
6542 template<typename Char>
AddCharacters(const Char * chars,int length)6543 inline void StringHasher::AddCharacters(const Char* chars, int length) {
6544 DCHECK(sizeof(Char) == 1 || sizeof(Char) == 2);
6545 int i = 0;
6546 if (is_array_index_) {
6547 for (; i < length; i++) {
6548 AddCharacter(chars[i]);
6549 if (!UpdateIndex(chars[i])) {
6550 i++;
6551 break;
6552 }
6553 }
6554 }
6555 for (; i < length; i++) {
6556 DCHECK(!is_array_index_);
6557 AddCharacter(chars[i]);
6558 }
6559 }
6560
6561
6562 template <typename schar>
HashSequentialString(const schar * chars,int length,uint32_t seed)6563 uint32_t StringHasher::HashSequentialString(const schar* chars,
6564 int length,
6565 uint32_t seed) {
6566 StringHasher hasher(length, seed);
6567 if (!hasher.has_trivial_hash()) hasher.AddCharacters(chars, length);
6568 return hasher.GetHashField();
6569 }
6570
6571
Hash(String * string,uint32_t seed)6572 uint32_t IteratingStringHasher::Hash(String* string, uint32_t seed) {
6573 IteratingStringHasher hasher(string->length(), seed);
6574 // Nothing to do.
6575 if (hasher.has_trivial_hash()) return hasher.GetHashField();
6576 ConsString* cons_string = String::VisitFlat(&hasher, string);
6577 // The string was flat.
6578 if (cons_string == NULL) return hasher.GetHashField();
6579 // This is a ConsString, iterate across it.
6580 ConsStringIteratorOp op(cons_string);
6581 int offset;
6582 while (NULL != (string = op.Next(&offset))) {
6583 String::VisitFlat(&hasher, string, offset);
6584 }
6585 return hasher.GetHashField();
6586 }
6587
6588
VisitOneByteString(const uint8_t * chars,int length)6589 void IteratingStringHasher::VisitOneByteString(const uint8_t* chars,
6590 int length) {
6591 AddCharacters(chars, length);
6592 }
6593
6594
VisitTwoByteString(const uint16_t * chars,int length)6595 void IteratingStringHasher::VisitTwoByteString(const uint16_t* chars,
6596 int length) {
6597 AddCharacters(chars, length);
6598 }
6599
6600
AsArrayIndex(uint32_t * index)6601 bool Name::AsArrayIndex(uint32_t* index) {
6602 return IsString() && String::cast(this)->AsArrayIndex(index);
6603 }
6604
6605
AsArrayIndex(uint32_t * index)6606 bool String::AsArrayIndex(uint32_t* index) {
6607 uint32_t field = hash_field();
6608 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
6609 return false;
6610 }
6611 return SlowAsArrayIndex(index);
6612 }
6613
6614
SetForwardedInternalizedString(String * canonical)6615 void String::SetForwardedInternalizedString(String* canonical) {
6616 DCHECK(IsInternalizedString());
6617 DCHECK(HasHashCode());
6618 if (canonical == this) return; // No need to forward.
6619 DCHECK(SlowEquals(canonical));
6620 DCHECK(canonical->IsInternalizedString());
6621 DCHECK(canonical->HasHashCode());
6622 WRITE_FIELD(this, kHashFieldOffset, canonical);
6623 // Setting the hash field to a tagged value sets the LSB, causing the hash
6624 // code to be interpreted as uninitialized. We use this fact to recognize
6625 // that we have a forwarded string.
6626 DCHECK(!HasHashCode());
6627 }
6628
6629
GetForwardedInternalizedString()6630 String* String::GetForwardedInternalizedString() {
6631 DCHECK(IsInternalizedString());
6632 if (HasHashCode()) return this;
6633 String* canonical = String::cast(READ_FIELD(this, kHashFieldOffset));
6634 DCHECK(canonical->IsInternalizedString());
6635 DCHECK(SlowEquals(canonical));
6636 DCHECK(canonical->HasHashCode());
6637 return canonical;
6638 }
6639
6640
GetConstructor()6641 Object* JSReceiver::GetConstructor() {
6642 return map()->constructor();
6643 }
6644
6645
HasProperty(Handle<JSReceiver> object,Handle<Name> name)6646 Maybe<bool> JSReceiver::HasProperty(Handle<JSReceiver> object,
6647 Handle<Name> name) {
6648 if (object->IsJSProxy()) {
6649 Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6650 return JSProxy::HasPropertyWithHandler(proxy, name);
6651 }
6652 Maybe<PropertyAttributes> result = GetPropertyAttributes(object, name);
6653 if (!result.has_value) return Maybe<bool>();
6654 return maybe(result.value != ABSENT);
6655 }
6656
6657
HasOwnProperty(Handle<JSReceiver> object,Handle<Name> name)6658 Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object,
6659 Handle<Name> name) {
6660 if (object->IsJSProxy()) {
6661 Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6662 return JSProxy::HasPropertyWithHandler(proxy, name);
6663 }
6664 Maybe<PropertyAttributes> result = GetOwnPropertyAttributes(object, name);
6665 if (!result.has_value) return Maybe<bool>();
6666 return maybe(result.value != ABSENT);
6667 }
6668
6669
GetPropertyAttributes(Handle<JSReceiver> object,Handle<Name> key)6670 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
6671 Handle<JSReceiver> object, Handle<Name> key) {
6672 uint32_t index;
6673 if (object->IsJSObject() && key->AsArrayIndex(&index)) {
6674 return GetElementAttribute(object, index);
6675 }
6676 LookupIterator it(object, key);
6677 return GetPropertyAttributes(&it);
6678 }
6679
6680
GetElementAttribute(Handle<JSReceiver> object,uint32_t index)6681 Maybe<PropertyAttributes> JSReceiver::GetElementAttribute(
6682 Handle<JSReceiver> object, uint32_t index) {
6683 if (object->IsJSProxy()) {
6684 return JSProxy::GetElementAttributeWithHandler(
6685 Handle<JSProxy>::cast(object), object, index);
6686 }
6687 return JSObject::GetElementAttributeWithReceiver(
6688 Handle<JSObject>::cast(object), object, index, true);
6689 }
6690
6691
IsDetached()6692 bool JSGlobalObject::IsDetached() {
6693 return JSGlobalProxy::cast(global_proxy())->IsDetachedFrom(this);
6694 }
6695
6696
IsDetachedFrom(GlobalObject * global)6697 bool JSGlobalProxy::IsDetachedFrom(GlobalObject* global) const {
6698 const PrototypeIterator iter(this->GetIsolate(),
6699 const_cast<JSGlobalProxy*>(this));
6700 return iter.GetCurrent() != global;
6701 }
6702
6703
GetOrCreateIdentityHash(Handle<JSReceiver> object)6704 Handle<Smi> JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver> object) {
6705 return object->IsJSProxy()
6706 ? JSProxy::GetOrCreateIdentityHash(Handle<JSProxy>::cast(object))
6707 : JSObject::GetOrCreateIdentityHash(Handle<JSObject>::cast(object));
6708 }
6709
6710
GetIdentityHash()6711 Object* JSReceiver::GetIdentityHash() {
6712 return IsJSProxy()
6713 ? JSProxy::cast(this)->GetIdentityHash()
6714 : JSObject::cast(this)->GetIdentityHash();
6715 }
6716
6717
HasElement(Handle<JSReceiver> object,uint32_t index)6718 Maybe<bool> JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) {
6719 if (object->IsJSProxy()) {
6720 Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6721 return JSProxy::HasElementWithHandler(proxy, index);
6722 }
6723 Maybe<PropertyAttributes> result = JSObject::GetElementAttributeWithReceiver(
6724 Handle<JSObject>::cast(object), object, index, true);
6725 if (!result.has_value) return Maybe<bool>();
6726 return maybe(result.value != ABSENT);
6727 }
6728
6729
HasOwnElement(Handle<JSReceiver> object,uint32_t index)6730 Maybe<bool> JSReceiver::HasOwnElement(Handle<JSReceiver> object,
6731 uint32_t index) {
6732 if (object->IsJSProxy()) {
6733 Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6734 return JSProxy::HasElementWithHandler(proxy, index);
6735 }
6736 Maybe<PropertyAttributes> result = JSObject::GetElementAttributeWithReceiver(
6737 Handle<JSObject>::cast(object), object, index, false);
6738 if (!result.has_value) return Maybe<bool>();
6739 return maybe(result.value != ABSENT);
6740 }
6741
6742
GetOwnElementAttribute(Handle<JSReceiver> object,uint32_t index)6743 Maybe<PropertyAttributes> JSReceiver::GetOwnElementAttribute(
6744 Handle<JSReceiver> object, uint32_t index) {
6745 if (object->IsJSProxy()) {
6746 return JSProxy::GetElementAttributeWithHandler(
6747 Handle<JSProxy>::cast(object), object, index);
6748 }
6749 return JSObject::GetElementAttributeWithReceiver(
6750 Handle<JSObject>::cast(object), object, index, false);
6751 }
6752
6753
all_can_read()6754 bool AccessorInfo::all_can_read() {
6755 return BooleanBit::get(flag(), kAllCanReadBit);
6756 }
6757
6758
set_all_can_read(bool value)6759 void AccessorInfo::set_all_can_read(bool value) {
6760 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
6761 }
6762
6763
all_can_write()6764 bool AccessorInfo::all_can_write() {
6765 return BooleanBit::get(flag(), kAllCanWriteBit);
6766 }
6767
6768
set_all_can_write(bool value)6769 void AccessorInfo::set_all_can_write(bool value) {
6770 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
6771 }
6772
6773
property_attributes()6774 PropertyAttributes AccessorInfo::property_attributes() {
6775 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
6776 }
6777
6778
set_property_attributes(PropertyAttributes attributes)6779 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
6780 set_flag(Smi::FromInt(AttributesField::update(flag()->value(), attributes)));
6781 }
6782
6783
IsCompatibleReceiver(Object * receiver)6784 bool AccessorInfo::IsCompatibleReceiver(Object* receiver) {
6785 if (!HasExpectedReceiverType()) return true;
6786 if (!receiver->IsJSObject()) return false;
6787 return FunctionTemplateInfo::cast(expected_receiver_type())
6788 ->IsTemplateFor(JSObject::cast(receiver)->map());
6789 }
6790
6791
clear_setter()6792 void ExecutableAccessorInfo::clear_setter() {
6793 set_setter(GetIsolate()->heap()->undefined_value(), SKIP_WRITE_BARRIER);
6794 }
6795
6796
6797 template<typename Derived, typename Shape, typename Key>
SetEntry(int entry,Handle<Object> key,Handle<Object> value)6798 void Dictionary<Derived, Shape, Key>::SetEntry(int entry,
6799 Handle<Object> key,
6800 Handle<Object> value) {
6801 SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
6802 }
6803
6804
6805 template<typename Derived, typename Shape, typename Key>
SetEntry(int entry,Handle<Object> key,Handle<Object> value,PropertyDetails details)6806 void Dictionary<Derived, Shape, Key>::SetEntry(int entry,
6807 Handle<Object> key,
6808 Handle<Object> value,
6809 PropertyDetails details) {
6810 DCHECK(!key->IsName() ||
6811 details.IsDeleted() ||
6812 details.dictionary_index() > 0);
6813 int index = DerivedHashTable::EntryToIndex(entry);
6814 DisallowHeapAllocation no_gc;
6815 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
6816 FixedArray::set(index, *key, mode);
6817 FixedArray::set(index+1, *value, mode);
6818 FixedArray::set(index+2, details.AsSmi());
6819 }
6820
6821
IsMatch(uint32_t key,Object * other)6822 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
6823 DCHECK(other->IsNumber());
6824 return key == static_cast<uint32_t>(other->Number());
6825 }
6826
6827
Hash(uint32_t key)6828 uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) {
6829 return ComputeIntegerHash(key, 0);
6830 }
6831
6832
HashForObject(uint32_t key,Object * other)6833 uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key,
6834 Object* other) {
6835 DCHECK(other->IsNumber());
6836 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0);
6837 }
6838
6839
SeededHash(uint32_t key,uint32_t seed)6840 uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) {
6841 return ComputeIntegerHash(key, seed);
6842 }
6843
6844
SeededHashForObject(uint32_t key,uint32_t seed,Object * other)6845 uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key,
6846 uint32_t seed,
6847 Object* other) {
6848 DCHECK(other->IsNumber());
6849 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed);
6850 }
6851
6852
AsHandle(Isolate * isolate,uint32_t key)6853 Handle<Object> NumberDictionaryShape::AsHandle(Isolate* isolate, uint32_t key) {
6854 return isolate->factory()->NewNumberFromUint(key);
6855 }
6856
6857
IsMatch(Handle<Name> key,Object * other)6858 bool NameDictionaryShape::IsMatch(Handle<Name> key, Object* other) {
6859 // We know that all entries in a hash table had their hash keys created.
6860 // Use that knowledge to have fast failure.
6861 if (key->Hash() != Name::cast(other)->Hash()) return false;
6862 return key->Equals(Name::cast(other));
6863 }
6864
6865
Hash(Handle<Name> key)6866 uint32_t NameDictionaryShape::Hash(Handle<Name> key) {
6867 return key->Hash();
6868 }
6869
6870
HashForObject(Handle<Name> key,Object * other)6871 uint32_t NameDictionaryShape::HashForObject(Handle<Name> key, Object* other) {
6872 return Name::cast(other)->Hash();
6873 }
6874
6875
AsHandle(Isolate * isolate,Handle<Name> key)6876 Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate,
6877 Handle<Name> key) {
6878 DCHECK(key->IsUniqueName());
6879 return key;
6880 }
6881
6882
DoGenerateNewEnumerationIndices(Handle<NameDictionary> dictionary)6883 void NameDictionary::DoGenerateNewEnumerationIndices(
6884 Handle<NameDictionary> dictionary) {
6885 DerivedDictionary::GenerateNewEnumerationIndices(dictionary);
6886 }
6887
6888
IsMatch(Handle<Object> key,Object * other)6889 bool ObjectHashTableShape::IsMatch(Handle<Object> key, Object* other) {
6890 return key->SameValue(other);
6891 }
6892
6893
Hash(Handle<Object> key)6894 uint32_t ObjectHashTableShape::Hash(Handle<Object> key) {
6895 return Smi::cast(key->GetHash())->value();
6896 }
6897
6898
HashForObject(Handle<Object> key,Object * other)6899 uint32_t ObjectHashTableShape::HashForObject(Handle<Object> key,
6900 Object* other) {
6901 return Smi::cast(other->GetHash())->value();
6902 }
6903
6904
AsHandle(Isolate * isolate,Handle<Object> key)6905 Handle<Object> ObjectHashTableShape::AsHandle(Isolate* isolate,
6906 Handle<Object> key) {
6907 return key;
6908 }
6909
6910
Shrink(Handle<ObjectHashTable> table,Handle<Object> key)6911 Handle<ObjectHashTable> ObjectHashTable::Shrink(
6912 Handle<ObjectHashTable> table, Handle<Object> key) {
6913 return DerivedHashTable::Shrink(table, key);
6914 }
6915
6916
6917 template <int entrysize>
IsMatch(Handle<Object> key,Object * other)6918 bool WeakHashTableShape<entrysize>::IsMatch(Handle<Object> key, Object* other) {
6919 return key->SameValue(other);
6920 }
6921
6922
6923 template <int entrysize>
Hash(Handle<Object> key)6924 uint32_t WeakHashTableShape<entrysize>::Hash(Handle<Object> key) {
6925 intptr_t hash = reinterpret_cast<intptr_t>(*key);
6926 return (uint32_t)(hash & 0xFFFFFFFF);
6927 }
6928
6929
6930 template <int entrysize>
HashForObject(Handle<Object> key,Object * other)6931 uint32_t WeakHashTableShape<entrysize>::HashForObject(Handle<Object> key,
6932 Object* other) {
6933 intptr_t hash = reinterpret_cast<intptr_t>(other);
6934 return (uint32_t)(hash & 0xFFFFFFFF);
6935 }
6936
6937
6938 template <int entrysize>
AsHandle(Isolate * isolate,Handle<Object> key)6939 Handle<Object> WeakHashTableShape<entrysize>::AsHandle(Isolate* isolate,
6940 Handle<Object> key) {
6941 return key;
6942 }
6943
6944
ClearCodeCache(Heap * heap)6945 void Map::ClearCodeCache(Heap* heap) {
6946 // No write barrier is needed since empty_fixed_array is not in new space.
6947 // Please note this function is used during marking:
6948 // - MarkCompactCollector::MarkUnmarkedObject
6949 // - IncrementalMarking::Step
6950 DCHECK(!heap->InNewSpace(heap->empty_fixed_array()));
6951 WRITE_FIELD(this, kCodeCacheOffset, heap->empty_fixed_array());
6952 }
6953
6954
EnsureSize(Handle<JSArray> array,int required_size)6955 void JSArray::EnsureSize(Handle<JSArray> array, int required_size) {
6956 DCHECK(array->HasFastSmiOrObjectElements());
6957 Handle<FixedArray> elts = handle(FixedArray::cast(array->elements()));
6958 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
6959 if (elts->length() < required_size) {
6960 // Doubling in size would be overkill, but leave some slack to avoid
6961 // constantly growing.
6962 Expand(array, required_size + (required_size >> 3));
6963 // It's a performance benefit to keep a frequently used array in new-space.
6964 } else if (!array->GetHeap()->new_space()->Contains(*elts) &&
6965 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
6966 // Expand will allocate a new backing store in new space even if the size
6967 // we asked for isn't larger than what we had before.
6968 Expand(array, required_size);
6969 }
6970 }
6971
6972
set_length(Smi * length)6973 void JSArray::set_length(Smi* length) {
6974 // Don't need a write barrier for a Smi.
6975 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
6976 }
6977
6978
AllowsSetElementsLength()6979 bool JSArray::AllowsSetElementsLength() {
6980 bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray();
6981 DCHECK(result == !HasExternalArrayElements());
6982 return result;
6983 }
6984
6985
SetContent(Handle<JSArray> array,Handle<FixedArrayBase> storage)6986 void JSArray::SetContent(Handle<JSArray> array,
6987 Handle<FixedArrayBase> storage) {
6988 EnsureCanContainElements(array, storage, storage->length(),
6989 ALLOW_COPIED_DOUBLE_ELEMENTS);
6990
6991 DCHECK((storage->map() == array->GetHeap()->fixed_double_array_map() &&
6992 IsFastDoubleElementsKind(array->GetElementsKind())) ||
6993 ((storage->map() != array->GetHeap()->fixed_double_array_map()) &&
6994 (IsFastObjectElementsKind(array->GetElementsKind()) ||
6995 (IsFastSmiElementsKind(array->GetElementsKind()) &&
6996 Handle<FixedArray>::cast(storage)->ContainsOnlySmisOrHoles()))));
6997 array->set_elements(*storage);
6998 array->set_length(Smi::FromInt(storage->length()));
6999 }
7000
7001
ic_total_count()7002 int TypeFeedbackInfo::ic_total_count() {
7003 int current = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
7004 return ICTotalCountField::decode(current);
7005 }
7006
7007
set_ic_total_count(int count)7008 void TypeFeedbackInfo::set_ic_total_count(int count) {
7009 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
7010 value = ICTotalCountField::update(value,
7011 ICTotalCountField::decode(count));
7012 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value));
7013 }
7014
7015
ic_with_type_info_count()7016 int TypeFeedbackInfo::ic_with_type_info_count() {
7017 int current = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
7018 return ICsWithTypeInfoCountField::decode(current);
7019 }
7020
7021
change_ic_with_type_info_count(int delta)7022 void TypeFeedbackInfo::change_ic_with_type_info_count(int delta) {
7023 if (delta == 0) return;
7024 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
7025 int new_count = ICsWithTypeInfoCountField::decode(value) + delta;
7026 // We can get negative count here when the type-feedback info is
7027 // shared between two code objects. The can only happen when
7028 // the debugger made a shallow copy of code object (see Heap::CopyCode).
7029 // Since we do not optimize when the debugger is active, we can skip
7030 // this counter update.
7031 if (new_count >= 0) {
7032 new_count &= ICsWithTypeInfoCountField::kMask;
7033 value = ICsWithTypeInfoCountField::update(value, new_count);
7034 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value));
7035 }
7036 }
7037
7038
ic_generic_count()7039 int TypeFeedbackInfo::ic_generic_count() {
7040 return Smi::cast(READ_FIELD(this, kStorage3Offset))->value();
7041 }
7042
7043
change_ic_generic_count(int delta)7044 void TypeFeedbackInfo::change_ic_generic_count(int delta) {
7045 if (delta == 0) return;
7046 int new_count = ic_generic_count() + delta;
7047 if (new_count >= 0) {
7048 new_count &= ~Smi::kMinValue;
7049 WRITE_FIELD(this, kStorage3Offset, Smi::FromInt(new_count));
7050 }
7051 }
7052
7053
initialize_storage()7054 void TypeFeedbackInfo::initialize_storage() {
7055 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(0));
7056 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(0));
7057 WRITE_FIELD(this, kStorage3Offset, Smi::FromInt(0));
7058 }
7059
7060
change_own_type_change_checksum()7061 void TypeFeedbackInfo::change_own_type_change_checksum() {
7062 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
7063 int checksum = OwnTypeChangeChecksum::decode(value);
7064 checksum = (checksum + 1) % (1 << kTypeChangeChecksumBits);
7065 value = OwnTypeChangeChecksum::update(value, checksum);
7066 // Ensure packed bit field is in Smi range.
7067 if (value > Smi::kMaxValue) value |= Smi::kMinValue;
7068 if (value < Smi::kMinValue) value &= ~Smi::kMinValue;
7069 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value));
7070 }
7071
7072
set_inlined_type_change_checksum(int checksum)7073 void TypeFeedbackInfo::set_inlined_type_change_checksum(int checksum) {
7074 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
7075 int mask = (1 << kTypeChangeChecksumBits) - 1;
7076 value = InlinedTypeChangeChecksum::update(value, checksum & mask);
7077 // Ensure packed bit field is in Smi range.
7078 if (value > Smi::kMaxValue) value |= Smi::kMinValue;
7079 if (value < Smi::kMinValue) value &= ~Smi::kMinValue;
7080 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value));
7081 }
7082
7083
own_type_change_checksum()7084 int TypeFeedbackInfo::own_type_change_checksum() {
7085 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
7086 return OwnTypeChangeChecksum::decode(value);
7087 }
7088
7089
matches_inlined_type_change_checksum(int checksum)7090 bool TypeFeedbackInfo::matches_inlined_type_change_checksum(int checksum) {
7091 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
7092 int mask = (1 << kTypeChangeChecksumBits) - 1;
7093 return InlinedTypeChangeChecksum::decode(value) == (checksum & mask);
7094 }
7095
7096
SMI_ACCESSORS(AliasedArgumentsEntry,aliased_context_slot,kAliasedContextSlot)7097 SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)
7098
7099
7100 Relocatable::Relocatable(Isolate* isolate) {
7101 isolate_ = isolate;
7102 prev_ = isolate->relocatable_top();
7103 isolate->set_relocatable_top(this);
7104 }
7105
7106
~Relocatable()7107 Relocatable::~Relocatable() {
7108 DCHECK_EQ(isolate_->relocatable_top(), this);
7109 isolate_->set_relocatable_top(prev_);
7110 }
7111
7112
SizeOf(Map * map,HeapObject * object)7113 int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
7114 return map->instance_size();
7115 }
7116
7117
ForeignIterateBody(ObjectVisitor * v)7118 void Foreign::ForeignIterateBody(ObjectVisitor* v) {
7119 v->VisitExternalReference(
7120 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
7121 }
7122
7123
7124 template<typename StaticVisitor>
ForeignIterateBody()7125 void Foreign::ForeignIterateBody() {
7126 StaticVisitor::VisitExternalReference(
7127 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
7128 }
7129
7130
ExternalOneByteStringIterateBody(ObjectVisitor * v)7131 void ExternalOneByteString::ExternalOneByteStringIterateBody(ObjectVisitor* v) {
7132 typedef v8::String::ExternalOneByteStringResource Resource;
7133 v->VisitExternalOneByteString(
7134 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
7135 }
7136
7137
7138 template <typename StaticVisitor>
ExternalOneByteStringIterateBody()7139 void ExternalOneByteString::ExternalOneByteStringIterateBody() {
7140 typedef v8::String::ExternalOneByteStringResource Resource;
7141 StaticVisitor::VisitExternalOneByteString(
7142 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
7143 }
7144
7145
ExternalTwoByteStringIterateBody(ObjectVisitor * v)7146 void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
7147 typedef v8::String::ExternalStringResource Resource;
7148 v->VisitExternalTwoByteString(
7149 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
7150 }
7151
7152
7153 template<typename StaticVisitor>
ExternalTwoByteStringIterateBody()7154 void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
7155 typedef v8::String::ExternalStringResource Resource;
7156 StaticVisitor::VisitExternalTwoByteString(
7157 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
7158 }
7159
7160
7161 template<int start_offset, int end_offset, int size>
IterateBody(HeapObject * obj,ObjectVisitor * v)7162 void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
7163 HeapObject* obj,
7164 ObjectVisitor* v) {
7165 v->VisitPointers(HeapObject::RawField(obj, start_offset),
7166 HeapObject::RawField(obj, end_offset));
7167 }
7168
7169
7170 template<int start_offset>
IterateBody(HeapObject * obj,int object_size,ObjectVisitor * v)7171 void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
7172 int object_size,
7173 ObjectVisitor* v) {
7174 v->VisitPointers(HeapObject::RawField(obj, start_offset),
7175 HeapObject::RawField(obj, object_size));
7176 }
7177
7178
7179 template<class Derived, class TableType>
CurrentKey()7180 Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() {
7181 TableType* table(TableType::cast(this->table()));
7182 int index = Smi::cast(this->index())->value();
7183 Object* key = table->KeyAt(index);
7184 DCHECK(!key->IsTheHole());
7185 return key;
7186 }
7187
7188
PopulateValueArray(FixedArray * array)7189 void JSSetIterator::PopulateValueArray(FixedArray* array) {
7190 array->set(0, CurrentKey());
7191 }
7192
7193
PopulateValueArray(FixedArray * array)7194 void JSMapIterator::PopulateValueArray(FixedArray* array) {
7195 array->set(0, CurrentKey());
7196 array->set(1, CurrentValue());
7197 }
7198
7199
CurrentValue()7200 Object* JSMapIterator::CurrentValue() {
7201 OrderedHashMap* table(OrderedHashMap::cast(this->table()));
7202 int index = Smi::cast(this->index())->value();
7203 Object* value = table->ValueAt(index);
7204 DCHECK(!value->IsTheHole());
7205 return value;
7206 }
7207
7208
7209 #undef TYPE_CHECKER
7210 #undef CAST_ACCESSOR
7211 #undef INT_ACCESSORS
7212 #undef ACCESSORS
7213 #undef ACCESSORS_TO_SMI
7214 #undef SMI_ACCESSORS
7215 #undef SYNCHRONIZED_SMI_ACCESSORS
7216 #undef NOBARRIER_SMI_ACCESSORS
7217 #undef BOOL_GETTER
7218 #undef BOOL_ACCESSORS
7219 #undef FIELD_ADDR
7220 #undef FIELD_ADDR_CONST
7221 #undef READ_FIELD
7222 #undef NOBARRIER_READ_FIELD
7223 #undef WRITE_FIELD
7224 #undef NOBARRIER_WRITE_FIELD
7225 #undef WRITE_BARRIER
7226 #undef CONDITIONAL_WRITE_BARRIER
7227 #undef READ_DOUBLE_FIELD
7228 #undef WRITE_DOUBLE_FIELD
7229 #undef READ_INT_FIELD
7230 #undef WRITE_INT_FIELD
7231 #undef READ_INTPTR_FIELD
7232 #undef WRITE_INTPTR_FIELD
7233 #undef READ_UINT32_FIELD
7234 #undef WRITE_UINT32_FIELD
7235 #undef READ_SHORT_FIELD
7236 #undef WRITE_SHORT_FIELD
7237 #undef READ_BYTE_FIELD
7238 #undef WRITE_BYTE_FIELD
7239 #undef NOBARRIER_READ_BYTE_FIELD
7240 #undef NOBARRIER_WRITE_BYTE_FIELD
7241
7242 } } // namespace v8::internal
7243
7244 #endif // V8_OBJECTS_INL_H_
7245