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